/**
	A wrapper around Flash 8's ExternalInterface; DojoExternalInterface is needed so that we
	can do a Flash 6 implementation of ExternalInterface, and be able
	to support having a single codebase that uses DojoExternalInterface
	across Flash versions rather than having two seperate source bases,
	where one uses ExternalInterface and the other uses DojoExternalInterface.

	DojoExternalInterface class does a variety of optimizations to bypass ExternalInterface's
	unbelievably bad performance so that we can have good performance
	on Safari; see the blog post
	http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
	for details.

	@author Brad Neuberg, bkn3@columbia.edu
*/

class DojoExternalInterfaceClass {
    #passthrough (toplevel:true) {
    import flash.external.ExternalInterface;
    }#
	var available = null;
	var flashMethods = [];
	var numArgs = null;
	var argData = null;
	var resultData = null;
//	var installing = false;
	var _id;

	function DojoExternalInterfaceClass(id){
		// extract the dojo base path
		//Debug.write('initialize', ExternalInterface.addCallback);

		// see if we need to do an express install
/*		var install = new ExpressInstall();
		if(install.needsUpdate){
			install.init();
			this.installing = true;
		}
*/
		// not loaded from the wrapper JS...
		if (id == null) return;

		this._id = id;

		// register our callback functions
		ExternalInterface.addCallback("startExec", this.startExec);
		ExternalInterface.addCallback("setNumberArguments", this.setNumberArguments);
		ExternalInterface.addCallback("chunkArgumentData", this.chunkArgumentData);
		ExternalInterface.addCallback("exec", this.exec);
		ExternalInterface.addCallback("getReturnLength", this.getReturnLength);
		ExternalInterface.addCallback("chunkReturnData", this.chunkReturnData);
		ExternalInterface.addCallback("endExec", this.endExec);

		// set whether communication is available
		this.available = ExternalInterface.available;
		this.call("loaded");
	}

	function addCallback(methodName, instance, method) {
		//Debug.write('addCallback', methodName, instance, method);
		// register DojoExternalInterface methodName with it's instance
		this.flashMethods[methodName] = instance;

		// tell JavaScript about DojoExternalInterface new method so we can create a proxy
		//Debug.write('calling dojo.flash.comm.' + this._id + "._addExternalInterfaceCallback", methodName, this._id);
		ExternalInterface.call("lz.embed.dojo.comm." + this._id + "._addExternalInterfaceCallback", methodName, this._id);

		return true;
	}

	function call(methodName, resultsCallback = null, ...parameters) {
		/*
		// we might have any number of optional arguments, so we have to
		// pass them in dynamically; strip out the results callback
		var parameters = [];
		for(var i = 0; i < arguments.length; i++){
			if(i != 1){ // skip the callback
				parameters.push(arguments[i]);
			}
		}
		*/

		var results = ExternalInterface.call(methodName, parameters);

		// immediately give the results back, since ExternalInterface is
		// synchronous
		if(resultsCallback != null && typeof resultsCallback != "undefined"){
			resultsCallback.call(null, results);
		}
	}

	/**
			Called by Flash to indicate to JavaScript that we are ready to have
			our Flash functions called. Calling loaded()
			will fire the dojo.flash.loaded() event, so that JavaScript can know that
			Flash has finished loading and adding its callbacks, and can begin to
			interact with the Flash file.
	*/
	function loaded(){
		Debug.write('loaded');
		//if (this.installing) return;
		this.call("lz.embed.dojo.loaded", null, this._id);
		//LzBrowserKernel.__jsready();
	}

	function startExec(){
		//Debug.write('startExec');
		this.numArgs = null;
		this.argData = null;
		this.resultData = null;
	}

	function setNumberArguments(numArgs){
		//Debug.write('setNumberArguments', numArgs);
		this.numArgs = numArgs;
		this.argData = [];
	}

	function chunkArgumentData(value, argIndex){
		//Debug.write('chunkArgumentData', value, argIndex);
		//getURL("javascript:dojo.debug('FLASH: chunkArgumentData, value="+value+", argIndex="+argIndex+"')");
		var currentValue = this.argData[argIndex];
		if(currentValue == null || typeof currentValue == "undefined"){
			this.argData[argIndex] = value;
		}else{
			this.argData[argIndex] += value;
		}
	}

	function exec(methodName){
		//Debug.write('exec', methodName);
		// decode all of the arguments that were passed in
		for(var i = 0; i < this.argData.length; i++){
			this.argData[i] =
				this.decodeData(this.argData[i]);
		}

		var instance = this.flashMethods[methodName];
		//Debug.write('instance', instance, instance[methodName]);
		this.resultData = instance[methodName].apply(
																			instance, this.argData) + '';
		//Debug.write('result', this.resultData);
		// encode the result data
		this.resultData =
			this.encodeData(this.resultData);

		//Debug.write('resultData', this.resultData);

		//getURL("javascript:dojo.debug('FLASH: encoded result data="+this.resultData+"')");
	}

	function getReturnLength(){
	 if(this.resultData == null ||
	 					typeof this.resultData == "undefined"){
	 	return 0;
	 }
	 var segments = Math.ceil(this.resultData.length / 1024);
	//Debug.write('getReturnLength', typeof this.resultData, this.resultData.length, segments);
	 return segments;
	}

	function chunkReturnData(segment){
		var numSegments = this.getReturnLength();
		var startCut = segment * 1024;
		var endCut = segment * 1024 + 1024;
		if(segment == (numSegments - 1)){
			endCut = segment * 1024 + this.resultData.length;
		}

		var piece = this.resultData.substring(startCut, endCut);

		//getURL("javascript:dojo.debug('FLASH: chunking return piece="+piece+"')");

		return piece;
	}

	function endExec(){
	}

	function decodeData(data){
		// we have to use custom encodings for certain characters when passing
		// them over; for example, passing a backslash over as //// from JavaScript
		// to Flash doesn't work
		data = this.replaceStr(data, "&custom_backslash;", "\\");

		data = this.replaceStr(data, "\\\'", "\'");
		data = this.replaceStr(data, "\\\"", "\"");
		//Debug.write('decodeData', data);

		return data;
	}

	function encodeData(data){
		//getURL("javascript:dojo.debug('inside flash, data before="+data+"')");

		// double encode all entity values, or they will be mis-decoded
		// by Flash when returned
		data = this.replaceStr(data, "&", "&");

		// certain XMLish characters break Flash's wire serialization for
		// ExternalInterface; encode these into a custom encoding, rather than
		// the standard entity encoding, because otherwise we won't be able to
		// differentiate between our own encoding and any entity characters
		// that are being used in the string itself
		data = this.replaceStr(data, '<', '&custom_lt;');
		data = this.replaceStr(data, '>', '&custom_gt;');

		// encode control characters and JavaScript delimiters
		data = this.replaceStr(data, "\n", "\\n");
		data = this.replaceStr(data, "\r", "\\r");
		data = this.replaceStr(data, "\f", "\\f");
		data = this.replaceStr(data, "'", "\\'");
		data = this.replaceStr(data, '"', '\"');

		//Debug.write('encodeData', data);
		//getURL("javascript:dojo.debug('inside flash, data after="+data+"')");
		return data;
	}

	/**
			Flash ActionScript has no String.replace method or support for
			Regular Expressions! We roll our own very simple one.
	*/
	function replaceStr(inputStr, replaceThis, withThis){
		var splitStr = inputStr.split(replaceThis)
		inputStr = splitStr.join(withThis)
		return inputStr;
	}

	/*
	function getDojoPath(){
		var url = _root._url;
		var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
		var path = url.substring(start);
		var end = path.indexOf("&");
		if(end != -1){
			path = path.substring(0, end);
		}
		return path;
	}
	*/
}

/* X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.          *
* Use is subject to license terms.                                        *
* X_LZ_COPYRIGHT_END ******************************************************/

// vim:ts=4:noet:tw=0:

/**
    A wrapper around Flash 8's ExternalInterface; DojoExternalInterface is needed so that we
    can do a Flash 6 implementation of ExternalInterface, and be able
    to support having a single codebase that uses DojoExternalInterface
    across Flash versions rather than having two seperate source bases,
    where one uses ExternalInterface and the other uses DojoExternalInterface.

    DojoExternalInterface class does a variety of optimizations to bypass ExternalInterface's
    unbelievably bad performance so that we can have good performance
    on Safari; see the blog post
    http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
    for details.

    @author Brad Neuberg, bkn3@columbia.edu
*/

class DojoExternalInterfaceClass {
    #passthrough (toplevel:true) {
    import flash.external.ExternalInterface;
    }#
    var available = null;
    var flashMethods = [];
    var numArgs = null;
    var argData = null;
    var resultData = null;
//  var installing = false;
    var _id;

    function DojoExternalInterfaceClass(id){
        // extract the dojo base path
        //Debug.write('initialize', ExternalInterface.addCallback);

        // see if we need to do an express install
/*      var install = new ExpressInstall();
        if(install.needsUpdate){
            install.init();
            this.installing = true;
        }
*/
        // not loaded from the wrapper JS...
        if (id == null) return;

        this._id = id;

        // register our callback functions
        ExternalInterface.addCallback("startExec", this.startExec);
        ExternalInterface.addCallback("setNumberArguments", this.setNumberArguments);
        ExternalInterface.addCallback("chunkArgumentData", this.chunkArgumentData);
        ExternalInterface.addCallback("exec", this.exec);
        ExternalInterface.addCallback("getReturnLength", this.getReturnLength);
        ExternalInterface.addCallback("chunkReturnData", this.chunkReturnData);
        ExternalInterface.addCallback("endExec", this.endExec);

        // set whether communication is available
        this.available = ExternalInterface.available;
        this.call("loaded");
    }

    function addCallback(methodName, instance, method) {
        //Debug.write('addCallback', methodName, instance, method);
        // register DojoExternalInterface methodName with it's instance
        this.flashMethods[methodName] = instance;

        // tell JavaScript about DojoExternalInterface new method so we can create a proxy
        //Debug.write('calling dojo.flash.comm.' + this._id + "._addExternalInterfaceCallback", methodName, this._id);
        ExternalInterface.call("lz.embed.dojo.comm." + this._id + "._addExternalInterfaceCallback", methodName, this._id);

        return true;
    }

    function call(methodName, resultsCallback = null, ...parameters) {
        /*
        // we might have any number of optional arguments, so we have to
        // pass them in dynamically; strip out the results callback
        var parameters = [];
        for(var i = 0; i < arguments.length; i++){
            if(i != 1){ // skip the callback
                parameters.push(arguments[i]);
            }
        }
        */

        var results = ExternalInterface.call(methodName, parameters);

        // immediately give the results back, since ExternalInterface is
        // synchronous
        if(resultsCallback != null && typeof resultsCallback != "undefined"){
            resultsCallback.call(null, results);
        }
    }

    /**
            Called by Flash to indicate to JavaScript that we are ready to have
            our Flash functions called. Calling loaded()
            will fire the dojo.flash.loaded() event, so that JavaScript can know that
            Flash has finished loading and adding its callbacks, and can begin to
            interact with the Flash file.
    */
    function loaded(){
        //Debug.write('loaded');
        //if (this.installing) return;
        this.call("lz.embed.dojo.loaded", null, this._id);
        //LzBrowserKernel.__jsready();
    }

    function startExec(){
        //Debug.write('startExec');
        this.numArgs = null;
        this.argData = null;
        this.resultData = null;
    }

    function setNumberArguments(numArgs){
        //Debug.write('setNumberArguments', numArgs);
        this.numArgs = numArgs;
        this.argData = [];
    }

    function chunkArgumentData(value, argIndex){
        //Debug.write('chunkArgumentData', value, argIndex);
        //getURL("javascript:dojo.debug('FLASH: chunkArgumentData, value="+value+", argIndex="+argIndex+"')");
        var currentValue = this.argData[argIndex];
        if(currentValue == null || typeof currentValue == "undefined"){
            this.argData[argIndex] = value;
        }else{
            this.argData[argIndex] += value;
        }
    }

    function exec(methodName){
        //Debug.write('exec', methodName);
        // decode all of the arguments that were passed in
        for(var i = 0; i < this.argData.length; i++){
            this.argData[i] =
                this.decodeData(this.argData[i]);
        }

        var instance = this.flashMethods[methodName];
        //Debug.write('instance', instance, instance[methodName]);
        this.resultData = instance[methodName].apply(
                                                                            instance, this.argData) + '';
        //Debug.write('result', this.resultData);
        // encode the result data
        this.resultData =
            this.encodeData(this.resultData);

        //Debug.write('resultData', this.resultData);

        //getURL("javascript:dojo.debug('FLASH: encoded result data="+this.resultData+"')");
    }

    function getReturnLength(){
     if(this.resultData == null ||
                        typeof this.resultData == "undefined"){
        return 0;
     }
     var segments = Math.ceil(this.resultData.length / 1024);
    //Debug.write('getReturnLength', typeof this.resultData, this.resultData.length, segments);
     return segments;
    }

    function chunkReturnData(segment){
        var numSegments = this.getReturnLength();
        var startCut = segment * 1024;
        var endCut = segment * 1024 + 1024;
        if(segment == (numSegments - 1)){
            endCut = segment * 1024 + this.resultData.length;
        }

        var piece = this.resultData.substring(startCut, endCut);

        //getURL("javascript:dojo.debug('FLASH: chunking return piece="+piece+"')");

        return piece;
    }

    function endExec(){
    }

    function decodeData(data){
        // we have to use custom encodings for certain characters when passing
        // them over; for example, passing a backslash over as //// from JavaScript
        // to Flash doesn't work
        data = this.replaceStr(data, "&custom_backslash;", "\\");

        data = this.replaceStr(data, "\\\'", "\'");
        data = this.replaceStr(data, "\\\"", "\"");
        //Debug.write('decodeData', data);

        return data;
    }

    function encodeData(data){
        //getURL("javascript:dojo.debug('inside flash, data before="+data+"')");

        // double encode all entity values, or they will be mis-decoded
        // by Flash when returned
        data = this.replaceStr(data, "&", "&");

        // certain XMLish characters break Flash's wire serialization for
        // ExternalInterface; encode these into a custom encoding, rather than
        // the standard entity encoding, because otherwise we won't be able to
        // differentiate between our own encoding and any entity characters
        // that are being used in the string itself
        data = this.replaceStr(data, '<', '&custom_lt;');
        data = this.replaceStr(data, '>', '&custom_gt;');

        // encode control characters and JavaScript delimiters
        data = this.replaceStr(data, "\n", "\\n");
        data = this.replaceStr(data, "\r", "\\r");
        data = this.replaceStr(data, "\f", "\\f");
        data = this.replaceStr(data, "'", "\\'");
        data = this.replaceStr(data, '"', '\"');

        //Debug.write('encodeData', data);
        //getURL("javascript:dojo.debug('inside flash, data after="+data+"')");
        return data;
    }

    /**
            Flash ActionScript has no String.replace method or support for
            Regular Expressions! We roll our own very simple one.
    */
    function replaceStr(inputStr, replaceThis, withThis){
        var splitStr = inputStr.split(replaceThis)
        inputStr = splitStr.join(withThis)
        return inputStr;
    }

    /*
    function getDojoPath(){
        var url = _root._url;
        var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
        var path = url.substring(start);
        var end = path.indexOf("&");
        if(end != -1){
            path = path.substring(0, end);
        }
        return path;
    }
    */
}

/* X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.          *
* Use is subject to license terms.                                        *
* X_LZ_COPYRIGHT_END ******************************************************/

// vim:ts=4:noet:tw=0:

Change 20080820-hqm-d by hqm@badtzmaru.home on 2008-08-20 15:18:10 EDT
    in /Users/hqm/openlaszlo/trunk/WEB-INF/lps/lfc
    for http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/lfc

Summary:

New Features: remove debug.write statement

Bugs Fixed:

Technical Reviewer: hqm
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:

Tests:

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@10725 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c


package com.threerings.util {

//import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Shape;

import flash.errors.IOError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.StatusEvent;
import flash.events.TextEvent;

import flash.geom.Point;

import flash.media.Video;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.system.SecurityDomain;

import flash.net.URLRequest;

import mx.core.ScrollPolicy;
import mx.core.UIComponent;

import mx.containers.Box;
import mx.controls.VideoDisplay;

import mx.events.VideoEvent;

import com.threerings.util.StringUtil;

import com.threerings.media.image.ImageUtil;

/**
 * A wrapper class for all media that will be placed on the screen.
 * Subject to change.
 */
public class MediaContainer extends Box
{
    /** An event we dispatch when our size is known. */
    public static const SIZE_KNOWN :String = "mediaSizeKnown";

    /** A log instance that can be shared by sprites. */
    protected static const log :Log = Log.getLog(MediaContainer);

    /**
     * Constructor.
     */
    public function MediaContainer (url :String = null)
    {
        if (url != null) {
            setMedia(url);
        }

        mouseEnabled = false;
        mouseChildren = true;
        verticalScrollPolicy = ScrollPolicy.OFF;
        horizontalScrollPolicy = ScrollPolicy.OFF;
    }

    /**
     * Get the media. If the media was loaded using a URL, this will
     * likely be the Loader object holding the real media.
     */
    public function getMedia () :DisplayObject
    {
        return _media;
    }

    /**
     * Configure the media to display.
     */
    public function setMedia (url :String) :void
    {
        if (Util.equals(_url, url)) {
            return; // no change
        }
        _url = url;

        // shutdown any previous media
        if (_media != null) {
            shutdown(false);
        }

        // set up the new media
        if (StringUtil.endsWith(url.toLowerCase(), ".flv")) {
            setupVideo(url);

        } else {
            setupSwfOrImage(url);
        }
    }

    /**
     * Configure our media as an instance of the specified class.
     */
    public function setMediaClass (clazz :Class) :void
    {
        setMediaObject(new clazz() as DisplayObject);
    }

    /**
     * Configure an already-instantiated DisplayObject as our media.
     */
    public function setMediaObject (disp :DisplayObject) :void
    {
        _url = null;
        if (_media != null) {
            shutdown(false);
        }

        if (disp is UIComponent) {
            addChild(disp);
        } else {
            rawChildren.addChild(disp);
        }
        _media = disp;
        updateContentDimensions(disp.width, disp.height);
    }

    /**
     * Configure this sprite to show a video.
     */
    protected function setupVideo (url :String) :void
    {
        var vid :VideoDisplay = new VideoDisplay();
        vid.autoPlay = false;
        _media = vid;
        addChild(vid);
        vid.addEventListener(ProgressEvent.PROGRESS, loadVideoProgress);
        vid.addEventListener(VideoEvent.READY, loadVideoReady);
        vid.addEventListener(VideoEvent.REWIND, videoDidRewind);

        // start it loading
        vid.source = url;
        vid.load();
    }

    /**
     * Configure this sprite to show an image or flash movie.
     */
    protected function setupSwfOrImage (url :String) :void
    {
        // create our loader and set up some event listeners
        var loader :Loader = new Loader();
        _media = loader;
        var info :LoaderInfo = loader.contentLoaderInfo;
        info.addEventListener(Event.COMPLETE, loadingComplete);
        info.addEventListener(IOErrorEvent.IO_ERROR, loadError);
        info.addEventListener(ProgressEvent.PROGRESS, loadProgress);

        // create a mask to prevent the media from drawing out of bounds
        if (getMaxContentWidth() < int.MAX_VALUE &&
                getMaxContentHeight() < int.MAX_VALUE) {
            configureMask(getMaxContentWidth(), getMaxContentHeight());
        }

        // start it loading, add it as a child
        loader.load(new URLRequest(url), getContext(url));
        rawChildren.addChild(loader);

        try {
            updateContentDimensions(info.width, info.height);
        } catch (err :Error) {
            // an error is thrown trying to access these props before they're
            // ready
        }
    }

    /**
     * Display a 'broken image' to indicate there were troubles with
     * loading the media.
     */
    protected function setupBrokenImage (w :int = -1, h :int = -1) :void
    {
        if (w == -1) {
            w = 100;
        }
        if (h == -1) {
            h = 100;
        }
        setMediaObject(ImageUtil.createErrorImage(w, h));
    }

    /**
     * Get the application domain being used by this media, or null if
     * none or not applicable.
     */
    public function getApplicationDomain () :ApplicationDomain
    {
        return (_media is Loader)
            ? (_media as Loader).contentLoaderInfo.applicationDomain
            : null;
    }

    /**
     * Unload the media we're displaying, clean up any resources.
     *
     * @param completely if true, we're going away and should stop
     * everything. Otherwise, we're just loading up new media.
     */
    public function shutdown (completely :Boolean = true) :void
    {
        try {
            // remove the mask
            if (_media != null && _media.mask != null) {
                rawChildren.removeChild(_media.mask);
                _media.mask = null;
            }

            if (_media is Loader) {
                var loader :Loader = (_media as Loader);
                // remove any listeners
                removeListeners(loader.contentLoaderInfo);

                // dispose of media
                try {
                    loader.close();
                } catch (ioe :IOError) {
                    // ignore
                }
                loader.unload();

                rawChildren.removeChild(loader);

            } else if (_media is VideoDisplay) {
                var vid :VideoDisplay = (_media as VideoDisplay);
                // remove any listeners
                vid.removeEventListener(ProgressEvent.PROGRESS,
                    loadVideoProgress);
                vid.removeEventListener(VideoEvent.READY, loadVideoReady);
                vid.removeEventListener(VideoEvent.REWIND, videoDidRewind);

                // dispose of media
                vid.pause();
                try {
                    vid.close();
                } catch (ioe :IOError) {
                    // ignore
                }
                vid.stop();

                // remove from hierarchy
                removeChild(vid);

            } else if (_media != null) {
                if (_media is UIComponent) {
                    removeChild(_media);
                } else {
                    rawChildren.removeChild(_media);
                }
            }
        } catch (ioe :IOError) {
            log.warning("Error shutting down media: " + ioe);
            log.logStackTrace(ioe);
        }

        // clean everything up
        _w = 0;
        _h = 0;
        _media = null;
    }

    /**
     * Get the width of the content, bounded by the maximum.
     */
    public function getContentWidth () :int
    {
        return Math.min(Math.abs(_w * getMediaScaleX()), getMaxContentWidth());
    }

    /**
     * Get the height of the content, bounded by the maximum.
     */
    public function getContentHeight () :int
    {
        return Math.min(Math.abs(_h * getMediaScaleY()), getMaxContentHeight());
    }

    /**
     * Get the maximum allowable width for our content.
     */
    public function getMaxContentWidth () :int
    {
        return int.MAX_VALUE;
    }

    /**
     * Get the maximum allowable height for our content.
     */
    public function getMaxContentHeight () :int
    {
        return int.MAX_VALUE;
    }

    /**
     * Get the X scaling factor to use on the actual media.
     */
    public function getMediaScaleX () :Number
    {
        return 1;
    }

    /**
     * Get the Y scaling factor to use on the actual media.
     */
    public function getMediaScaleY () :Number
    {
        return 1;
    }

    /**
     * Return the LoaderContext that should be used to load the media
     * at the specified url.
     */
    protected function getContext (url :String) :LoaderContext
    {
        if (isImage(url)) {
            // load images into our domain so that we can view their pixels
            return new LoaderContext(true,
                new ApplicationDomain(ApplicationDomain.currentDomain),
                SecurityDomain.currentDomain);

        } else {
            // share nothing, trust nothing
            return new LoaderContext(false, null, null);
        }
    }

    /**
     * Does the specified url represent an image?
     */
    protected function isImage (url :String) :Boolean
    {
        // look at the last 4 characters in the lowercased url
        switch (url.toLowerCase().slice(-4)) {
        case ".png":
        case ".jpg":
        case ".gif":
            return true;

        default:
            return false;
        }
    }

    /**
     * Remove our listeners from the LoaderInfo object.
     */
    protected function removeListeners (info :LoaderInfo) :void
    {
        info.removeEventListener(Event.COMPLETE, loadingComplete);
        info.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
        info.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
    }

    /**
     * A callback to receive IO_ERROR events.
     */
    protected function loadError (event :IOErrorEvent) :void
    {
        setupBrokenImage(-1, -1);
    }

    /**
     * A callback to receive PROGRESS events.
     */
    protected function loadProgress (event :ProgressEvent) :void
    {
        updateLoadingProgress(event.bytesLoaded, event.bytesTotal);
        var info :LoaderInfo = (event.target as LoaderInfo);
        try {
            updateContentDimensions(info.width, info.height);
        } catch (err :Error) {
            // an error is thrown trying to access these props before they're
            // ready
        }
    }

    /**
     * A callback to receive PROGRESS events on the video.
     */
    protected function loadVideoProgress (event :ProgressEvent) :void
    {
        var vid :VideoDisplay = (event.currentTarget as VideoDisplay);
        updateContentDimensions(vid.videoWidth, vid.videoHeight);

        updateLoadingProgress(vid.bytesLoaded, vid.bytesTotal);
    }

    /**
     * A callback to receive READY events for video.
     */
    protected function loadVideoReady (event :VideoEvent) :void
    {
        var vid :VideoDisplay = (event.currentTarget as VideoDisplay);
        updateContentDimensions(vid.videoWidth, vid.videoHeight);
        updateLoadingProgress(1, 1);

        vid.play();

        // remove the two listeners
        vid.removeEventListener(ProgressEvent.PROGRESS, loadVideoProgress);
        vid.removeEventListener(VideoEvent.READY, loadVideoReady);
    }

    /**
     * Callback function to receive COMPLETE events for swfs or images.
     */
    protected function loadingComplete (event :Event) :void
    {
        var info :LoaderInfo = (event.target as LoaderInfo);
        removeListeners(info);

//        trace("Loading complete: " + info.url +
//            ", childAllowsParent=" + info.childAllowsParent +
//            ", parentAllowsChild=" + info.parentAllowsChild +
//            ", sameDomain=" + info.sameDomain);

        updateContentDimensions(info.width, info.height);
        updateLoadingProgress(1, 1);

//        // Bitmap smoothing
//        if (_media is Loader) {
//            var l :Loader = Loader(_media);
//            try {
//                if (l.content is Bitmap) {
//                    Bitmap(l.content).smoothing = true;
//                    trace("--- made bitmap smooth");
//                }
//            } catch (er :Error) {
//                trace("--- error bitmap smooth");
//            }
//        }
    }

    /**
     * Called when the video auto-rewinds.
     */
    protected function videoDidRewind (event :VideoEvent) :void
    {
        (_media as VideoDisplay).play();
    }

    /**
     * Configure the mask for this object.
     */
    protected function configureMask (ww :int, hh :int) :void
    {
        var mask :Shape;
        if (_media.mask != null) {
            mask = (_media.mask as Shape);

        } else {
            mask = new Shape();
            // the mask must be added to the display list (which is wacky)
            rawChildren.addChild(mask);
            _media.mask = mask;
        }

        mask.graphics.clear();
        mask.graphics.beginFill(0xFFFFFF);
        mask.graphics.drawRect(0, 0, ww, hh);
        mask.graphics.endFill();
    }

    /**
     * Called during loading as we figure out how big the content we're
     * loading is.
     */
    protected function updateContentDimensions (ww :int, hh :int) :void
    {
        // update our saved size, and possibly notify our container
        if (_w != ww || _h != hh) {
            _w = ww;
            _h = hh;
            // TODO: I think that I'll want to create a subclass of the
            // basic media container which does things that are usefulish
            // but separate from MsoySprite. SIZE_KNOWN is one of those
            // things that should probably be moved. Maybe BaseMediaContainer
            // and MediaContainer? FancyMediaContainer?
            dispatchEvent(new Event(SIZE_KNOWN));
            contentDimensionsUpdated();
        }
    }

    /**
     * Called when we know the true size of the content.
     */
    protected function contentDimensionsUpdated () :void
    {
        // nada, by default
    }

    /**
     * Update the graphics to indicate how much is loaded.
     */
    protected function updateLoadingProgress (
            soFar :Number, total :Number) :void
    {
        // nada, by default
    }

    /** The unaltered URL of the content we're displaying. */
    protected var _url :String;

    /** The unscaled width of our content. */
    protected var _w :int;

    /** The unscaled height of our content. */
    protected var _h :int;

    /** Either a Loader or a VideoDisplay. */
    protected var _media :DisplayObject;
}
}

package com.threerings.util {

//import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Shape;
import flash.display.Sprite;

import flash.errors.IOError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.StatusEvent;
import flash.events.TextEvent;

import flash.geom.Point;

import flash.media.Video;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.system.SecurityDomain;

import flash.net.URLRequest;

import com.threerings.util.StringUtil;

import com.threerings.media.image.ImageUtil;

/**
 * A wrapper class for all media that will be placed on the screen.
 * Subject to change.
 */
public class MediaContainer extends Sprite
{
    /** An event we dispatch when our size is known. */
    public static const SIZE_KNOWN :String = "mediaSizeKnown";

    /** A log instance that can be shared by sprites. */
    protected static const log :Log = Log.getLog(MediaContainer);

    /**
     * Constructor.
     */
    public function MediaContainer (url :String = null)
    {
        if (url != null) {
            setMedia(url);
        }

        mouseEnabled = false;
        mouseChildren = true;
    }

    /**
     * Get the media. If the media was loaded using a URL, this will
     * likely be the Loader object holding the real media.
     */
    public function getMedia () :DisplayObject
    {
        return _media;
    }

    /**
     * Configure the media to display.
     */
    public function setMedia (url :String) :void
    {
        if (Util.equals(_url, url)) {
            return; // no change
        }
        _url = url;

        // shutdown any previous media
        if (_media != null) {
            shutdown(false);
        }

        // set up the new media
        if (StringUtil.endsWith(url.toLowerCase(), ".flv")) {
            setupVideo(url);

        } else {
            setupSwfOrImage(url);
        }
    }

    /**
     * Configure our media as an instance of the specified class.
     */
    public function setMediaClass (clazz :Class) :void
    {
        setMediaObject(new clazz() as DisplayObject);
    }

    /**
     * Configure an already-instantiated DisplayObject as our media.
     */
    public function setMediaObject (disp :DisplayObject) :void
    {
        _url = null;
        if (_media != null) {
            shutdown(false);
        }

        addChild(disp);
        _media = disp;
        updateContentDimensions(disp.width, disp.height);
    }

    /**
     * Configure this sprite to show a video.
     */
    protected function setupVideo (url :String) :void
    {
//        var vid :VideoDisplay = new VideoDisplay();
//        vid.autoPlay = false;
//        _media = vid;
//        addChild(vid);
//        vid.addEventListener(ProgressEvent.PROGRESS, loadVideoProgress);
//        vid.addEventListener(VideoEvent.READY, loadVideoReady);
//        vid.addEventListener(VideoEvent.REWIND, videoDidRewind);
//
//        // start it loading
//        vid.source = url;
//        vid.load();
    }

    /**
     * Configure this sprite to show an image or flash movie.
     */
    protected function setupSwfOrImage (url :String) :void
    {
        // create our loader and set up some event listeners
        var loader :Loader = new Loader();
        _media = loader;
        var info :LoaderInfo = loader.contentLoaderInfo;
        info.addEventListener(Event.COMPLETE, loadingComplete);
        info.addEventListener(IOErrorEvent.IO_ERROR, loadError);
        info.addEventListener(ProgressEvent.PROGRESS, loadProgress);

        // create a mask to prevent the media from drawing out of bounds
        if (getMaxContentWidth() < int.MAX_VALUE &&
                getMaxContentHeight() < int.MAX_VALUE) {
            configureMask(getMaxContentWidth(), getMaxContentHeight());
        }

        // start it loading, add it as a child
        loader.load(new URLRequest(url), getContext(url));
        addChild(loader);

        try {
            updateContentDimensions(info.width, info.height);
        } catch (err :Error) {
            // an error is thrown trying to access these props before they're
            // ready
        }
    }

    /**
     * Display a 'broken image' to indicate there were troubles with
     * loading the media.
     */
    protected function setupBrokenImage (w :int = -1, h :int = -1) :void
    {
        if (w == -1) {
            w = 100;
        }
        if (h == -1) {
            h = 100;
        }
        setMediaObject(ImageUtil.createErrorImage(w, h));
    }

    /**
     * Get the application domain being used by this media, or null if
     * none or not applicable.
     */
    public function getApplicationDomain () :ApplicationDomain
    {
        return (_media is Loader)
            ? (_media as Loader).contentLoaderInfo.applicationDomain
            : null;
    }

    /**
     * Unload the media we're displaying, clean up any resources.
     *
     * @param completely if true, we're going away and should stop
     * everything. Otherwise, we're just loading up new media.
     */
    public function shutdown (completely :Boolean = true) :void
    {
        try {
            // remove the mask
            if (_media != null && _media.mask != null) {
                removeChild(_media.mask);
                _media.mask = null;
            }

            if (_media is Loader) {
                var loader :Loader = (_media as Loader);
                // remove any listeners
                removeListeners(loader.contentLoaderInfo);

                // dispose of media
                try {
                    loader.close();
                } catch (ioe :IOError) {
                    // ignore
                }
                loader.unload();

                removeChild(loader);

//            } else if (_media is VideoDisplay) {
//                var vid :VideoDisplay = (_media as VideoDisplay);
//                // remove any listeners
//                vid.removeEventListener(ProgressEvent.PROGRESS,
//                    loadVideoProgress);
//                vid.removeEventListener(VideoEvent.READY, loadVideoReady);
//                vid.removeEventListener(VideoEvent.REWIND, videoDidRewind);
//
//                // dispose of media
//                vid.pause();
//                try {
//                    vid.close();
//                } catch (ioe :IOError) {
//                    // ignore
//                }
//                vid.stop();
//
//                // remove from hierarchy
//                removeChild(vid);

            } else if (_media != null) {
                removeChild(_media);
            }
        } catch (ioe :IOError) {
            log.warning("Error shutting down media: " + ioe);
            log.logStackTrace(ioe);
        }

        // clean everything up
        _w = 0;
        _h = 0;
        _media = null;
    }

    /**
     * Get the width of the content, bounded by the maximum.
     */
    public function getContentWidth () :int
    {
        return Math.min(Math.abs(_w * getMediaScaleX()), getMaxContentWidth());
    }

    /**
     * Get the height of the content, bounded by the maximum.
     */
    public function getContentHeight () :int
    {
        return Math.min(Math.abs(_h * getMediaScaleY()), getMaxContentHeight());
    }

    /**
     * Get the maximum allowable width for our content.
     */
    public function getMaxContentWidth () :int
    {
        return int.MAX_VALUE;
    }

    /**
     * Get the maximum allowable height for our content.
     */
    public function getMaxContentHeight () :int
    {
        return int.MAX_VALUE;
    }

    /**
     * Get the X scaling factor to use on the actual media.
     */
    public function getMediaScaleX () :Number
    {
        return 1;
    }

    /**
     * Get the Y scaling factor to use on the actual media.
     */
    public function getMediaScaleY () :Number
    {
        return 1;
    }

    /**
     * Return the LoaderContext that should be used to load the media
     * at the specified url.
     */
    protected function getContext (url :String) :LoaderContext
    {
        if (isImage(url)) {
            // load images into our domain so that we can view their pixels
            return new LoaderContext(true,
                new ApplicationDomain(ApplicationDomain.currentDomain),
                SecurityDomain.currentDomain);

        } else {
            // share nothing, trust nothing
            return new LoaderContext(false, null, null);
        }
    }

    /**
     * Does the specified url represent an image?
     */
    protected function isImage (url :String) :Boolean
    {
        // look at the last 4 characters in the lowercased url
        switch (url.toLowerCase().slice(-4)) {
        case ".png":
        case ".jpg":
        case ".gif":
            return true;

        default:
            return false;
        }
    }

    /**
     * Remove our listeners from the LoaderInfo object.
     */
    protected function removeListeners (info :LoaderInfo) :void
    {
        info.removeEventListener(Event.COMPLETE, loadingComplete);
        info.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
        info.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
    }

    /**
     * A callback to receive IO_ERROR events.
     */
    protected function loadError (event :IOErrorEvent) :void
    {
        setupBrokenImage(-1, -1);
    }

    /**
     * A callback to receive PROGRESS events.
     */
    protected function loadProgress (event :ProgressEvent) :void
    {
        updateLoadingProgress(event.bytesLoaded, event.bytesTotal);
        var info :LoaderInfo = (event.target as LoaderInfo);
        try {
            updateContentDimensions(info.width, info.height);
        } catch (err :Error) {
            // an error is thrown trying to access these props before they're
            // ready
        }
    }

    /**
     * A callback to receive PROGRESS events on the video.
     */
    protected function loadVideoProgress (event :ProgressEvent) :void
    {
//        var vid :VideoDisplay = (event.currentTarget as VideoDisplay);
//        updateContentDimensions(vid.videoWidth, vid.videoHeight);
//
//        updateLoadingProgress(vid.bytesLoaded, vid.bytesTotal);
    }

    /**
     * A callback to receive READY events for video.
     */
//    protected function loadVideoReady (event :VideoEvent) :void
//    {
//        var vid :VideoDisplay = (event.currentTarget as VideoDisplay);
//        updateContentDimensions(vid.videoWidth, vid.videoHeight);
//        updateLoadingProgress(1, 1);
//
//        vid.play();
//
//        // remove the two listeners
//        vid.removeEventListener(ProgressEvent.PROGRESS, loadVideoProgress);
//        vid.removeEventListener(VideoEvent.READY, loadVideoReady);
//    }

    /**
     * Callback function to receive COMPLETE events for swfs or images.
     */
    protected function loadingComplete (event :Event) :void
    {
        var info :LoaderInfo = (event.target as LoaderInfo);
        removeListeners(info);

//        trace("Loading complete: " + info.url +
//            ", childAllowsParent=" + info.childAllowsParent +
//            ", parentAllowsChild=" + info.parentAllowsChild +
//            ", sameDomain=" + info.sameDomain);

        updateContentDimensions(info.width, info.height);
        updateLoadingProgress(1, 1);
    }

    /**
     * Called when the video auto-rewinds.
     */
//    protected function videoDidRewind (event :VideoEvent) :void
//    {
//        (_media as VideoDisplay).play();
//    }

    /**
     * Configure the mask for this object.
     */
    protected function configureMask (ww :int, hh :int) :void
    {
        var mask :Shape;
        if (_media.mask != null) {
            mask = (_media.mask as Shape);

        } else {
            mask = new Shape();
            // the mask must be added to the display list (which is wacky)
            addChild(mask);
            _media.mask = mask;
        }

        mask.graphics.clear();
        mask.graphics.beginFill(0xFFFFFF);
        mask.graphics.drawRect(0, 0, ww, hh);
        mask.graphics.endFill();
    }

    /**
     * Called during loading as we figure out how big the content we're
     * loading is.
     */
    protected function updateContentDimensions (ww :int, hh :int) :void
    {
        // update our saved size, and possibly notify our container
        if (_w != ww || _h != hh) {
            _w = ww;
            _h = hh;
            // TODO: I think that I'll want to create a subclass of the
            // basic media container which does things that are usefulish
            // but separate from MsoySprite. SIZE_KNOWN is one of those
            // things that should probably be moved. Maybe BaseMediaContainer
            // and MediaContainer? FancyMediaContainer?
            dispatchEvent(new Event(SIZE_KNOWN));
            contentDimensionsUpdated();
        }
    }

    /**
     * Called when we know the true size of the content.
     */
    protected function contentDimensionsUpdated () :void
    {
        // nada, by default
    }

    /**
     * Update the graphics to indicate how much is loaded.
     */
    protected function updateLoadingProgress (
            soFar :Number, total :Number) :void
    {
        // nada, by default
    }

    /** The unaltered URL of the content we're displaying. */
    protected var _url :String;

    /** The unscaled width of our content. */
    protected var _w :int;

    /** The unscaled height of our content. */
    protected var _h :int;

    /** Either a Loader or a VideoDisplay. */
    protected var _media :DisplayObject;
}
}

Convert MediaContainer to be just a subclass of Sprite, so that I can
de-flex the 'world' portions of metasoy.

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4506 542714f4-19e9-0310-aa3c-eee0fc999fb1


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed 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.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.core
{
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.utils.Version;
    import com.google.analytics.v4.Configuration;

    /**
     * The BrowserInfo class.
     */
    public class BrowserInfo
    {
        private var _config:Configuration;
        private var _info:Environment;

        /**
         * Creates a new BrowserInfo instance.
         * @param info The Environment reference of the BrowserInfo instance.
         */
        public function BrowserInfo( config:Configuration, info:Environment )
        {
            _config = config;
            _info   = info;
        }

        /**
         * Language encoding for the browser.
         *
Some browsers don't set this, in which case it is set to "-".

         *
Example : utmcs=ISO-8859-1

         */
        public function get utmcs():String
        {
            return _info.languageEncoding;
        }

        /**
         * The Screen resolution
         *
Example : utmsr=2400x1920

         */
        public function get utmsr():String
        {
            return _info.screenWidth + "x" + _info.screenHeight;
        }

        /**
         * Screen color depth
         *
Example :utmsc=24-bit

         */
        public function get utmsc():String
        {
            return _info.screenColorDepth + "-bit";
        }

        /**
         * Browser language.
         *
Example :utmul=pt-br

         */
        public function get utmul():String
        {
            return _info.language.toLowerCase();
        }

        /**
         * Indicates if browser is Java-enabled.
         *
Example :utmje=1

         */
        public function get utmje():String
        {
            return "0"; //not supported
        }

        /**
         * Flash Version.
         *
Example :utmfl=9.0%20r48

         */
        public function get utmfl():String
        {
            if( _config.detectFlash )
            {
                var v:Version = _info.flashVersion;
                return v.major+"."+v.minor+" r"+v.build;
            }

            return "-";
        }

        /**
         * Returns a Variables object representation.
         * @return a Variables object representation.
         */
        public function toVariables():Variables
        {
            var variables:Variables = new Variables();
                variables.URIencode = true;
                variables.utmcs = utmcs;
                variables.utmsr = utmsr;
                variables.utmsc = utmsc;
                variables.utmul = utmul;
                variables.utmje = utmje;
                variables.utmfl = utmfl;
            return variables;
        }

        /**
         * Returns the url String representation of the object.
         * @return the url String representation of the object.
         */
        public function toURLString():String
        {
            var v:Variables = toVariables();
            return v.toString();
        }
    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed 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.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.core
{
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    import core.version;

    public class BrowserInfo
    {
        private var _config:Configuration;
        private var _info:Environment;

        /**
         * Creates a new BrowserInfo instance.
         * @param info The Environment reference of the BrowserInfo instance.
         */
        public function BrowserInfo( config:Configuration, info:Environment )
        {
            _config = config;
            _info   = info;
        }

        /**
         * Language encoding for the browser.
         *
Some browsers don't set this, in which case it is set to "-".

         *
Example : utmcs=ISO-8859-1

         */
        public function get utmcs():String
        {
            return _info.languageEncoding;
        }

        /**
         * The Screen resolution
         *
Example : utmsr=2400x1920

         */
        public function get utmsr():String
        {
            return _info.screenWidth + "x" + _info.screenHeight;
        }

        /**
         * Screen color depth
         *
Example :utmsc=24-bit

         */
        public function get utmsc():String
        {
            return _info.screenColorDepth + "-bit";
        }

        /**
         * Browser language.
         *
Example :utmul=pt-br

         */
        public function get utmul():String
        {
            return _info.language.toLowerCase();
        }

        /**
         * Indicates if browser is Java-enabled.
         *
Example :utmje=1

         */
        public function get utmje():String
        {
            return "0"; //not supported
        }

        /**
         * Flash Version.
         *
Example :utmfl=9.0%20r48

         */
        public function get utmfl():String
        {
            if( _config.detectFlash )
            {
                var v:version = _info.flashVersion;
                return v.major+"."+v.minor+" r"+v.build;
            }

            return "-";
        }

        /**
         * Returns a Variables object representation.
         * @return a Variables object representation.
         */
        public function toVariables():Variables
        {
            var variables:Variables = new Variables();
                variables.URIencode = true;
                variables.utmcs = utmcs;
                variables.utmsr = utmsr;
                variables.utmsc = utmsc;
                variables.utmul = utmul;
                variables.utmje = utmje;
                variables.utmfl = utmfl;
            return variables;
        }

        /**
         * Returns the url String representation of the object.
         * @return the url String representation of the object.
         */
        public function toURLString():String
        {
            var v:Variables = toVariables();
            return v.toString();
        }
    }
}

replace class Version by core.version

replace class Version by core.version


/*
 * FLINT PARTICLE SYSTEM
 * .....................
 *
 * Author: Richard Lord
 * Copyright (c) Richard Lord 2008-2011
 * http://flintparticles.org
 *
 *
 * Licence Agreement
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.flintparticles.twoD.actions
{
	import org.flintparticles.common.actions.ActionBase;
	import org.flintparticles.common.emitters.Emitter;
	import org.flintparticles.common.initializers.Initializer;
	import org.flintparticles.common.particles.Particle;
	import org.flintparticles.twoD.particles.Particle2D;
	import org.flintparticles.twoD.zones.Zone2D;

	import flash.geom.Point;

	[DefaultProperty("zone")]

	/**
	 * The TweenToZone action adjusts the particle's position between two
	 * locations as it ages. The start location is wherever the particle starts
	 * from, depending on the emitter and the initializers. The end position is
	 * a random point within the specified zone. The current position is relative
	 * to the particle's energy,
	 * which changes as the particle ages in accordance with the energy easing
	 * function used. This action should be used in conjunction with the Age action.
	 */

	public class TweenToZone extends ActionBase implements Initializer
	{
		private var _zone:Zone2D;

		/**
		 * The constructor creates a TweenToZone action for use by an emitter.
		 * To add a TweenToZone to all particles created by an emitter, use the
		 * emitter's addAction method.
		 *
		 * @see org.flintparticles.common.emitters.Emitter#addAction()
		 *
		 * @param zone The zone for the particle's position when its energy is 0.
		 */
		public function TweenToZone( zone:Zone2D )
		{
			_zone = zone;
			priority = -10;
		}

		/**
		 * The zone for the particle's position when its energy is 0.
		 */
		public function get zone():Zone2D
		{
			return _zone;
		}
		public function set zone( value:Zone2D ):void
		{
			_zone = value;
		}

		/**
		 *
		 */
		override public function addedToEmitter( emitter:Emitter ):void
		{
			if( ! emitter.hasInitializer( this ) )
			{
				emitter.addInitializer( this );
			}
		}

		override public function removedFromEmitter( emitter:Emitter ):void
		{
			emitter.removeInitializer( this );
		}

		/**
		 *
		 */
		public function initialize( emitter:Emitter, particle:Particle ):void
		{
			var p:Particle2D = Particle2D( particle );
			var pt:Point = _zone.getLocation();
			var data:TweenToZoneData = new TweenToZoneData( p.x, p.y, pt.x, pt.y );
			p.dictionary[this] = data;
		}

		/**
		 * Calculates the current position of the particle based on it's energy.
		 *
		 *
This method is called by the emitter and need not be called by the
		 * user.

		 *
		 * @param emitter The Emitter that created the particle.
		 * @param particle The particle to be updated.
		 * @param time The duration of the frame - used for time based updates.
		 *
		 * @see org.flintparticles.common.actions.Action#update()
		 */
		override public function update( emitter:Emitter, particle:Particle, time:Number ):void
		{
			var p:Particle2D = Particle2D( particle );
			if( ! p.dictionary[this] )
			{
				initialize( emitter, particle );
			}
			var data:TweenToZoneData = p.dictionary[this];
			p.x = data.endX + data.diffX * p.energy;
			p.y = data.endY + data.diffY * p.energy;
		}
	}
}

class TweenToZoneData
{
	public var diffX:Number;
	public var diffY:Number;
	public var endX:Number;
	public var endY:Number;

	public function TweenToZoneData( startX:Number, startY:Number, endX:Number, endY:Number )
	{
		this.diffX = startX - endX;
		this.diffY = startY - endY;
		this.endX = endX;
		this.endY = endY;
	}
}

/*
 * FLINT PARTICLE SYSTEM
 * .....................
 *
 * Author: Richard Lord
 * Copyright (c) Richard Lord 2008-2011
 * http://flintparticles.org
 *
 *
 * Licence Agreement
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.flintparticles.twoD.actions
{
	import org.flintparticles.common.actions.ActionBase;
	import org.flintparticles.common.emitters.Emitter;
	import org.flintparticles.common.initializers.Initializer;
	import org.flintparticles.common.particles.Particle;
	import org.flintparticles.twoD.particles.Particle2D;
	import org.flintparticles.twoD.zones.Zone2D;

	import flash.geom.Point;

	[DefaultProperty("zone")]

	/**
	 * The TweenToZone action adjusts the particle's position between two
	 * locations as it ages. The start location is wherever the particle starts
	 * from, depending on the emitter and the initializers. The end position is
	 * a random point within the specified zone. The current position is relative
	 * to the particle's energy,
	 * which changes as the particle ages in accordance with the energy easing
	 * function used. This action should be used in conjunction with the Age action.
	 */

	public class TweenToZone extends ActionBase implements Initializer
	{
		private var _zone:Zone2D;

		/**
		 * The constructor creates a TweenToZone action for use by an emitter.
		 * To add a TweenToZone to all particles created by an emitter, use the
		 * emitter's addAction method.
		 *
		 * @see org.flintparticles.common.emitters.Emitter#addAction()
		 *
		 * @param zone The zone for the particle's position when its energy is 0.
		 */
		public function TweenToZone( zone:Zone2D=null )
		{
			_zone = zone;
			priority = -10;
		}

		/**
		 * The zone for the particle's position when its energy is 0.
		 */
		public function get zone():Zone2D
		{
			return _zone;
		}
		public function set zone( value:Zone2D ):void
		{
			_zone = value;
		}

		/**
		 *
		 */
		override public function addedToEmitter( emitter:Emitter ):void
		{
			if( ! emitter.hasInitializer( this ) )
			{
				emitter.addInitializer( this );
			}
		}

		override public function removedFromEmitter( emitter:Emitter ):void
		{
			emitter.removeInitializer( this );
		}

		/**
		 *
		 */
		public function initialize( emitter:Emitter, particle:Particle ):void
		{
			var p:Particle2D = Particle2D( particle );
			var pt:Point = _zone.getLocation();
			var data:TweenToZoneData = new TweenToZoneData( p.x, p.y, pt.x, pt.y );
			p.dictionary[this] = data;
		}

		/**
		 * Calculates the current position of the particle based on it's energy.
		 *
		 *
This method is called by the emitter and need not be called by the
		 * user.

		 *
		 * @param emitter The Emitter that created the particle.
		 * @param particle The particle to be updated.
		 * @param time The duration of the frame - used for time based updates.
		 *
		 * @see org.flintparticles.common.actions.Action#update()
		 */
		override public function update( emitter:Emitter, particle:Particle, time:Number ):void
		{
			var p:Particle2D = Particle2D( particle );
			if( ! p.dictionary[this] )
			{
				initialize( emitter, particle );
			}
			var data:TweenToZoneData = p.dictionary[this];
			p.x = data.endX + data.diffX * p.energy;
			p.y = data.endY + data.diffY * p.energy;
		}
	}
}

class TweenToZoneData
{
	public var diffX:Number;
	public var diffY:Number;
	public var endX:Number;
	public var endY:Number;

	public function TweenToZoneData( startX:Number, startY:Number, endX:Number, endY:Number )
	{
		this.diffX = startX - endX;
		this.diffY = startY - endY;
		this.endX = endX;
		this.endY = endY;
	}
}

Add default parameter to support MXML.

Add default parameter to support MXML.


package aerys.minko.render.material.basic
{
	import aerys.minko.render.DrawCall;
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.ShaderInstance;
	import aerys.minko.render.shader.ShaderSettings;
	import aerys.minko.render.shader.part.DiffuseShaderPart;
	import aerys.minko.render.shader.part.animation.VertexAnimationShaderPart;
	import aerys.minko.type.enum.Blending;
	import aerys.minko.type.enum.BlendingSource;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.enum.StencilAction;
	import aerys.minko.type.enum.TriangleCulling;

	/**
	 * The BasicShader is a simple shader program handling hardware vertex
	 * animations (skinning and morphing), a diffuse color or a texture and
	 * a directional light.
	 *
	 *

	 *

	 * 	Property Name
	 * 	Source
	 * 	Type
	 * 	Description
	 * 	Requires
	 *

	 *

	 * 	lightEnabled
	 * 	Scene
	 * 	Boolean
	 * 	Whether the light is enabled or not on the scene.
	 * 	lightDirection, lightAmbient, lightAmbientColor, lightDiffuse, lightDiffuseColor
	 *

	 *

	 * 	lightDirection
	 * 	Scene
	 * 	Vector4
	 * 	The direction of the light.
	 *
	 *

	 *

	 * 	lightAmbient
	 * 	Scene
	 * 	Number
	 * 	The ambient factor of the light.
	 *
	 *

	 *

	 * 	lightAmbientColor
	 * 	Scene
	 * 	uint or Vector4
	 * 	The ambient color of the light.
	 *
	 *

	 *

	 * 	lightDiffuse
	 * 	Scene
	 * 	Number
	 * 	The diffuse factor of the light
	 *
	 *

	 *

	 * 	lightDiffuseColor
	 * 	Scene
	 * 	uint or Vector4
	 * 	The diffuse color of the light.
	 *
	 *

	 *

	 * 	lightEnabled
	 * 	Mesh
	 * 	Boolean
	 * 	Whether the light is enabled or not on the mesh.
	 *
	 *

	 *

	 * 	diffuseMap
	 * 	Mesh
	 * 	TextureResource
	 * 	The texture to use for rendering.
	 *
	 *

	 *

	 * 	diffuseColor
	 * 	Mesh
	 * 	uint or Vector4
	 * 	The color to use for rendering. If the "diffuseMap" binding is set, this
	 * 	value is not used.
	 *
	 *

	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class BasicShader extends Shader
	{
		private var _vertexAnimationPart	: VertexAnimationShaderPart	= null;
		private var _diffuseShaderPart		: DiffuseShaderPart			= null;

		private var _vertexNormal			: SFloat					= null;

		protected function get diffuse() : DiffuseShaderPart
		{
			return _diffuseShaderPart;
		}

		protected function get vertexAnimation() : VertexAnimationShaderPart
		{
			return _vertexAnimationPart;
		}

		/**
		 * @param priority Default value is 0.
		 * @param target Default value is null.
		 */
		public function BasicShader(target		: RenderTarget	= null,
									priority	: Number		= 0.)
		{
			super(target, priority);

			// init shader parts
			_vertexAnimationPart	= new VertexAnimationShaderPart(this);
			_diffuseShaderPart		= new DiffuseShaderPart(this);
		}

		override protected function initializeSettings(settings : ShaderSettings) : void
		{
			super.initializeSettings(settings);

			// depth test
			settings.depthWriteEnabled = meshBindings.getConstant(
				BasicProperties.DEPTH_WRITE_ENABLED, true
			);
			settings.depthTest = meshBindings.getConstant(
				BasicProperties.DEPTH_TEST, DepthTest.LESS
			);

			settings.triangleCulling = meshBindings.getConstant(
				BasicProperties.TRIANGLE_CULLING, TriangleCulling.BACK
			);

			// stencil operations
			settings.stencilTriangleFace = meshBindings.getConstant(
				BasicProperties.STENCIL_TRIANGLE_FACE, TriangleCulling.BOTH
			);
			settings.stencilCompareMode = meshBindings.getConstant(
				BasicProperties.STENCIL_COMPARE_MODE, DepthTest.EQUAL
			);
			settings.stencilActionOnBothPass = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_BOTH_PASS, StencilAction.KEEP
			);
			settings.stencilActionOnDepthFail = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_DEPTH_FAIL, StencilAction.KEEP
			);
			settings.stencilActionOnDepthPassStencilFail = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_DEPTH_PASS_STENCIL_FAIL, StencilAction.KEEP
			);
			settings.stencilReferenceValue = meshBindings.getConstant(
				BasicProperties.STENCIL_REFERENCE_VALUE, 0
			);
			settings.stencilReadMask = meshBindings.getConstant(
				BasicProperties.STENCIL_READ_MASK, 255
			);
			settings.stencilWriteMask = meshBindings.getConstant(
				BasicProperties.STENCIL_WRITE_MASK, 255
			);

			// blending and priority
			var blending : uint = meshBindings.getConstant(
				BasicProperties.BLENDING, Blending.NORMAL
			);

			if ((blending & 0xff) == BlendingSource.SOURCE_ALPHA)
			{
				settings.priority -= 0.5;
				settings.depthSortDrawCalls = true;
			}

			settings.blending			= blending;
			settings.enabled			= true;
			settings.scissorRectangle	= null;
		}

		/**
		 * @return The position of the vertex in clip space (normalized
		 * screen space).
		 *
		 */
		override protected function getVertexPosition() : SFloat
		{
			var triangleCulling	: uint	= meshBindings.getConstant(
				BasicProperties.TRIANGLE_CULLING, TriangleCulling.BACK
			);

			_vertexNormal = _vertexAnimationPart.getAnimatedVertexNormal();
			// flip the normal when the triangle culling is flipped
			if (triangleCulling == TriangleCulling.FRONT)
				_vertexNormal = multiply(vertexNormal, float4(-1, -1, -1, 1));
			_vertexNormal = deltaLocalToWorld(_vertexNormal);

			return localToScreen(
				_vertexAnimationPart.getAnimatedVertexPosition()
			);
		}

		/**
		 * @return The pixel color using a diffuse color/map and an optional
		 * directional light.
		 */
		override protected function getPixelColor() : SFloat
		{
			var diffuse	: SFloat = _diffuseShaderPart.getDiffuse();

			if (meshBindings.propertyExists(BasicProperties.ALPHA_THRESHOLD))
			{
				var alphaThreshold : SFloat = meshBindings.getParameter(
					BasicProperties.ALPHA_THRESHOLD, 1
				);

				kill(subtract(0.5, lessThan(diffuse.w, alphaThreshold)));
			}

			return diffuse;
		}
	}
}

package aerys.minko.render.material.basic
{
	import aerys.minko.render.DrawCall;
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.ShaderInstance;
	import aerys.minko.render.shader.ShaderSettings;
	import aerys.minko.render.shader.part.DiffuseShaderPart;
	import aerys.minko.render.shader.part.animation.VertexAnimationShaderPart;
	import aerys.minko.type.enum.Blending;
	import aerys.minko.type.enum.BlendingSource;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.enum.StencilAction;
	import aerys.minko.type.enum.TriangleCulling;

	/**
	 * The BasicShader is a simple shader program handling hardware vertex
	 * animations (skinning and morphing), a diffuse color or a texture and
	 * a directional light.
	 *
	 *

	 *

	 * 	Property Name
	 * 	Source
	 * 	Type
	 * 	Description
	 * 	Requires
	 *

	 *

	 * 	lightEnabled
	 * 	Scene
	 * 	Boolean
	 * 	Whether the light is enabled or not on the scene.
	 * 	lightDirection, lightAmbient, lightAmbientColor, lightDiffuse, lightDiffuseColor
	 *

	 *

	 * 	lightDirection
	 * 	Scene
	 * 	Vector4
	 * 	The direction of the light.
	 *
	 *

	 *

	 * 	lightAmbient
	 * 	Scene
	 * 	Number
	 * 	The ambient factor of the light.
	 *
	 *

	 *

	 * 	lightAmbientColor
	 * 	Scene
	 * 	uint or Vector4
	 * 	The ambient color of the light.
	 *
	 *

	 *

	 * 	lightDiffuse
	 * 	Scene
	 * 	Number
	 * 	The diffuse factor of the light
	 *
	 *

	 *

	 * 	lightDiffuseColor
	 * 	Scene
	 * 	uint or Vector4
	 * 	The diffuse color of the light.
	 *
	 *

	 *

	 * 	lightEnabled
	 * 	Mesh
	 * 	Boolean
	 * 	Whether the light is enabled or not on the mesh.
	 *
	 *

	 *

	 * 	diffuseMap
	 * 	Mesh
	 * 	TextureResource
	 * 	The texture to use for rendering.
	 *
	 *

	 *

	 * 	diffuseColor
	 * 	Mesh
	 * 	uint or Vector4
	 * 	The color to use for rendering. If the "diffuseMap" binding is set, this
	 * 	value is not used.
	 *
	 *

	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class BasicShader extends Shader
	{
		private var _vertexAnimationPart	: VertexAnimationShaderPart	= null;
		private var _diffuseShaderPart		: DiffuseShaderPart			= null;

		private var _vertexNormal			: SFloat					= null;

		protected function get diffuse() : DiffuseShaderPart
		{
			return _diffuseShaderPart;
		}

		protected function get vertexAnimation() : VertexAnimationShaderPart
		{
			return _vertexAnimationPart;
		}

		/**
		 * @param priority Default value is 0.
		 * @param target Default value is null.
		 */
		public function BasicShader(target		: RenderTarget	= null,
									priority	: Number		= 0.)
		{
			super(target, priority);

			// init shader parts
			_vertexAnimationPart	= new VertexAnimationShaderPart(this);
			_diffuseShaderPart		= new DiffuseShaderPart(this);
		}

		override protected function initializeSettings(settings : ShaderSettings) : void
		{
			super.initializeSettings(settings);

			// depth test
			settings.depthWriteEnabled = meshBindings.getConstant(
				BasicProperties.DEPTH_WRITE_ENABLED, true
			);
			settings.depthTest = meshBindings.getConstant(
				BasicProperties.DEPTH_TEST, DepthTest.LESS
			);

			settings.triangleCulling = meshBindings.getConstant(
				BasicProperties.TRIANGLE_CULLING, TriangleCulling.BACK
			);

			// stencil operations
			settings.stencilTriangleFace = meshBindings.getConstant(
				BasicProperties.STENCIL_TRIANGLE_FACE, TriangleCulling.BOTH
			);
			settings.stencilCompareMode = meshBindings.getConstant(
				BasicProperties.STENCIL_COMPARE_MODE, DepthTest.EQUAL
			);
			settings.stencilActionOnBothPass = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_BOTH_PASS, StencilAction.KEEP
			);
			settings.stencilActionOnDepthFail = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_DEPTH_FAIL, StencilAction.KEEP
			);
			settings.stencilActionOnDepthPassStencilFail = meshBindings.getConstant(
				BasicProperties.STENCIL_ACTION_DEPTH_PASS_STENCIL_FAIL, StencilAction.KEEP
			);
			settings.stencilReferenceValue = meshBindings.getConstant(
				BasicProperties.STENCIL_REFERENCE_VALUE, 0
			);
			settings.stencilReadMask = meshBindings.getConstant(
				BasicProperties.STENCIL_READ_MASK, 255
			);
			settings.stencilWriteMask = meshBindings.getConstant(
				BasicProperties.STENCIL_WRITE_MASK, 255
			);

			// blending and priority
			var blending : uint = meshBindings.getConstant(
				BasicProperties.BLENDING, Blending.NORMAL
			);

			if ((blending & 0xff) == BlendingSource.SOURCE_ALPHA)
			{
				settings.priority -= 0.5;
				settings.depthSortDrawCalls = true;
			}

			settings.blending			= blending;
			settings.enabled			= true;
			settings.scissorRectangle	= null;
		}

		/**
		 * @return The position of the vertex in clip space (normalized
		 * screen space).
		 *
		 */
		override protected function getVertexPosition() : SFloat
		{
			var triangleCulling	: uint	= meshBindings.getConstant(
				BasicProperties.TRIANGLE_CULLING, TriangleCulling.BACK
			);

			_vertexNormal = _vertexAnimationPart.getAnimatedVertexNormal();
			// flip the normal when the triangle culling is flipped
			if (triangleCulling == TriangleCulling.FRONT)
				_vertexNormal = multiply(vertexNormal, float4(-1, -1, -1, 1));
			_vertexNormal = deltaLocalToWorld(_vertexNormal);

			return localToScreen(
				_vertexAnimationPart.getAnimatedVertexPosition()
			);
		}

		/**
		 * @return The pixel color using a diffuse color/map and an optional
		 * directional light.
		 */
		override protected function getPixelColor() : SFloat
		{
			var diffuse	: SFloat = _diffuseShaderPart.getDiffuseColor();

			if (meshBindings.propertyExists(BasicProperties.ALPHA_THRESHOLD))
			{
				var alphaThreshold : SFloat = meshBindings.getParameter(
					BasicProperties.ALPHA_THRESHOLD, 1
				);

				kill(subtract(0.5, lessThan(diffuse.w, alphaThreshold)));
			}

			return diffuse;
		}
	}
}

update shader to use DiffuseShaderPart.getDiffuseColor() instead of DiffuseShaderPart.getDiffuse()


/**
 * Copyright (c) 2009 Digital Primates IT Consulting Group
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * @author     Michael Labriola <labriola@digitalprimates.net>
 * @version
 **/
package org.flexunit.runners.model {
	import flash.utils.Dictionary;

	import flex.lang.reflect.Klass;
	import flex.lang.reflect.Method;

	import mx.collections.IViewCursor;

	import org.flexunit.runner.manipulation.MethodSorter;

	/**
	 * Wraps a class to be run, providing method validation and annotation searching
	 */
	public class TestClass {
		private var klass:Class;
		private var _klassInfo:Klass
		private var metaDataDictionary:Dictionary = new Dictionary( false );

	//TODO: I'm guessing JDK should be replaced with something else
		/**
		 * Creates a {@code TestClass} wrapping {@code klass}. Each time this
		 * constructor executes, the class is scanned for annotations, which can be
		 * an expensive process (we hope in future JDK's it will not be.) Therefore,
		 * try to share instances of {@code TestClass} where possible.
		 */
		public function TestClass( klass:Class ) {
			this.klass = klass;
			_klassInfo = new Klass( klass );

			//Ensures that the Order argument of the Test, Begin, After and BeforeClass and AfterClass are respected
			var sorter:MethodSorter = new MethodSorter( _klassInfo.methods );
			sorter.sort();
			var cursor:IViewCursor = sorter.createCursor();

			var method:Method;
			while (!cursor.afterLast ) {
				method = cursor.current as Method;
				addToMetaDataDictionary( new FrameworkMethod( method ) );
				cursor.moveNext();
			}
		}

		public function get klassInfo():Klass {
			return _klassInfo;
		}

		private function addToMetaDataDictionary( testMethod:FrameworkMethod ):void {
			var metaDataList:XMLList = testMethod.metadata;
			var metaTag:String;
			var entry:Array;

			if ( metaDataList ) {
				for ( var i:int=0; i<metaDataList.length(); i++ ) {
					metaTag = metaDataList[ i ].@name;

					entry = metaDataDictionary[ metaTag ];

					if ( !entry ) {
						metaDataDictionary[ metaTag ] = new Array();
						entry = metaDataDictionary[ metaTag ]
					}

					entry.push( testMethod );
				}
			}
		}

		/**
		 * Returns the underlying class.
		 */
		public function get asClass():Class {
			return klass;
		}

		/**
		 * Returns the class's name.
		 */
		public function get name():String {
			if (!klassInfo) {
				return "null";
			}

			return klassInfo.name;
		}

		/**
		 * Returns the metadata on this class
		 */
		public function get metadata():XMLList {
			if ( !klassInfo ) {
				return null;
			}

			return klassInfo.metadata;
		}

		/**
		 * Returns, efficiently, all the non-overridden methods in this class and
		 * its superclasses that contain the metadata tag {@code metaTag}.
		 */
		public function getMetaDataMethods( metaTag:String ):Array {
			var methodArray:Array;
			methodArray = metaDataDictionary[ metaTag ];

			if ( !methodArray ) {
				methodArray = new Array();
			}

			return methodArray;
		}

		public function toString():String {
			var str:String = "TestClass ";

			if ( _klassInfo ) {
				str += ( "(" + _klassInfo.name + ")" );
			}

			return str;
		}
	}
}

/**
 * Copyright (c) 2009 Digital Primates IT Consulting Group
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * @author     Michael Labriola <labriola@digitalprimates.net>
 * @version
 **/
package org.flexunit.runners.model {
	import flash.utils.Dictionary;

	import flex.lang.reflect.Klass;
	import flex.lang.reflect.Method;

	import mx.collections.IViewCursor;

	import org.flexunit.runner.manipulation.MethodSorter;

	/**
	 * Wraps a class to be run, providing method validation and annotation searching
	 */
	public class TestClass {
		private var klass:Class;
		private var _klassInfo:Klass
		private var metaDataDictionary:Dictionary = new Dictionary( false );

	//TODO: I'm guessing JDK should be replaced with something else
		/**
		 * Creates a {@code TestClass} wrapping {@code klass}. Each time this
		 * constructor executes, the class is scanned for annotations, which can be
		 * an expensive process (we hope in future JDK's it will not be.) Therefore,
		 * try to share instances of {@code TestClass} where possible.
		 */
		public function TestClass( klass:Class ) {
			this.klass = klass;
			_klassInfo = new Klass( klass );

			//Ensures that the Order argument of the Test, Begin, After and BeforeClass and AfterClass are respected
			var sorter:MethodSorter = new MethodSorter( _klassInfo.methods );
			sorter.sort();
			var cursor:IViewCursor = sorter.createCursor();

			var method:Method;
			while (!cursor.afterLast ) {
				method = cursor.current as Method;
				addToMetaDataDictionary( new FrameworkMethod( method ) );
				cursor.moveNext();
			}
		}

		public function get klassInfo():Klass {
			return _klassInfo;
		}

		private function addToMetaDataDictionary( testMethod:FrameworkMethod ):void {
			var metaDataList:XMLList = testMethod.metadata;
			var metaTag:String;
			var entry:Array;

			if ( metaDataList ) {
				for ( var i:int=0; i<metaDataList.length(); i++ ) {
					metaTag = metaDataList[ i ].@name;

					entry = metaDataDictionary[ metaTag ];

					if ( !entry ) {
						metaDataDictionary[ metaTag ] = new Array();
						entry = metaDataDictionary[ metaTag ]
					}

					var found:Boolean = false;
					//Before we push this onto the stack, we take a quick pass to ensure it is not already there
					//this covers the case where someone double flags a test with a piece of metadata
					//bugID="FXU-33")
 					for ( var j:int=0; j<entry.length; j++ ) {
						if ( ( entry[ j ] as FrameworkMethod ).method === testMethod.method ) {
							found = true;
							break;
						}
					}

					if ( !found ) {
						entry.push( testMethod );
					}
				}
			}
		}

		/**
		 * Returns the underlying class.
		 */
		public function get asClass():Class {
			return klass;
		}

		/**
		 * Returns the class's name.
		 */
		public function get name():String {
			if (!klassInfo) {
				return "null";
			}

			return klassInfo.name;
		}

		/**
		 * Returns the metadata on this class
		 */
		public function get metadata():XMLList {
			if ( !klassInfo ) {
				return null;
			}

			return klassInfo.metadata;
		}

		/**
		 * Returns, efficiently, all the non-overridden methods in this class and
		 * its superclasses that contain the metadata tag {@code metaTag}.
		 */
		public function getMetaDataMethods( metaTag:String ):Array {
			var methodArray:Array;
			methodArray = metaDataDictionary[ metaTag ];

			if ( !methodArray ) {
				methodArray = new Array();
			}

			return methodArray;
		}

		public function toString():String {
			var str:String = "TestClass ";

			if ( _klassInfo ) {
				str += ( "(" + _klassInfo.name + ")" );
			}

			return str;
		}
	}
}

Fix for FXU-33

Fix for FXU-33

git-svn-id: 9278a788294a4258aac04586390fc35fb4a5f335@7348 a9308255-753e-0410-a2e9-80b3fbc4fff6


package aerys.minko.render.resource.texture
{
	import aerys.minko.render.resource.Context3DResource;
	import aerys.minko.type.enum.SamplerFormat;

	import flash.display.BitmapData;
	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 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 static const FORMAT_COMPRESSED_ALPHA 	: String 	= Context3DTextureFormat.COMPRESSED_ALPHA;

		private static const TEXTURE_FORMAT_TO_SAMPLER	: Array 	= []
		{
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_BGRA] 				= SamplerFormat.RGBA;
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_COMPRESSED] 		= SamplerFormat.COMPRESSED;
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_COMPRESSED_ALPHA] 	= SamplerFormat.COMPRESSED_ALPHA;
		}

		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 _format 		: String 		= FORMAT_BGRA;

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

		private var _update			: Boolean		= false;

		public function get format() : uint
		{
			return TEXTURE_FORMAT_TO_SAMPLER[_format];
		}

        public function get mipMapping() : Boolean
        {
            return _mipmap;
        }

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

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

		public function TextureResource(width   : uint  = 0,
                                        height  : uint  = 0)
		{
            _width = width;
            _height = height;
		}

		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;

			if (_bitmapData == null || _bitmapData.width != w || _bitmapData.height != h)
				_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;
			_bitmapData		= null;
			_update 		= true;

			var oldWidth	: Number = _width;
			var oldHeight	: Number = _height;
			var oldMipmap	: Boolean = _mipmap;

			atf.position 	= 6;

			var formatByte 	: uint = atf.readUnsignedByte();

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

			atf.position 	= 0;

			if (_atfFormat == 5)
				_format = FORMAT_COMPRESSED_ALPHA;
			else if (_atfFormat == 3)
				_format = FORMAT_COMPRESSED;

			if (_texture
				&& (oldMipmap != _mipmap
					|| oldWidth != _width
					|| oldHeight != _height))
			{
				_texture.dispose();
				_texture = null;
			}
		}

		public function getTexture(context : Context3DResource) : TextureBase
		{
			if (!_texture && _width && _height)
			{
				if (_texture)
					_texture.dispose();

				_texture = context.createTexture(
					_width,
					_height,
					_format,
					_bitmapData == null && _atf == null
				);
			}

			if (_update)
			{
				_update = false;
				uploadBitmapDataWithMipMaps();
			}

			_atf = null;
			_bitmapData = null;

			return _texture;
		}

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

					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);
			}
		}

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

package aerys.minko.render.resource.texture
{
	import aerys.minko.render.resource.Context3DResource;
	import aerys.minko.type.enum.SamplerFormat;

	import flash.display.BitmapData;
	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 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	= 'bgra';
		private static const FORMAT_COMPRESSED			: String	= 'compressed';
		private static const FORMAT_COMPRESSED_ALPHA 	: String 	= 'compressedAlpha';

		private static const TEXTURE_FORMAT_TO_SAMPLER	: Array 	= []
		{
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_BGRA] 				= SamplerFormat.RGBA;
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_COMPRESSED] 		= SamplerFormat.COMPRESSED;
			TEXTURE_FORMAT_TO_SAMPLER[FORMAT_COMPRESSED_ALPHA] 	= SamplerFormat.COMPRESSED_ALPHA;
		}

		private var _texture		: Texture;
		private var _mipmap			: Boolean;

		private var _bitmapData		: BitmapData;
		private var _atf			: ByteArray;
		private var _atfFormat		: uint;
		private var _format 		: String;

		private var _width			: Number;
		private var _height			: Number;

		private var _update			: Boolean;

		public function get format() : uint
		{
			return TEXTURE_FORMAT_TO_SAMPLER[_format];
		}

        public function get mipMapping() : Boolean
        {
            return _mipmap;
        }

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

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

		public function TextureResource(width   : uint  = 0,
                                        height  : uint  = 0)
		{
            _width = width;
            _height = height;
			_format = FORMAT_BGRA;
		}

		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;

			if (_bitmapData == null || _bitmapData.width != w || _bitmapData.height != h)
				_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
				&& (_format	!= FORMAT_BGRA
					|| mipmap != _mipmap
					|| bitmapData.width != _width
					|| bitmapData.height != _height))
			{
				_texture.dispose();
				_texture = null;
			}

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

			_mipmap	= mipmap;
			_update	= true;
		}

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

			var oldWidth	: Number = _width;
			var oldHeight	: Number = _height;
			var oldMipmap	: Boolean = _mipmap;
			var oldFormat	: String = _format;

			atf.position 	= 6;

			var formatByte 	: uint = atf.readUnsignedByte();

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

			atf.position 	= 0;

			if (_atfFormat == 5)
				_format = FORMAT_COMPRESSED_ALPHA;
			else if (_atfFormat == 3)
				_format = FORMAT_COMPRESSED;
			else
				_format = FORMAT_BGRA;

			if (_texture
				&& (oldFormat != _format
					|| oldMipmap != _mipmap
					|| oldWidth != _width
					|| oldHeight != _height))
			{
				_texture.dispose();
				_texture = null;
			}
		}

		public function getTexture(context : Context3DResource) : TextureBase
		{
			if (!_texture && _width && _height)
			{
				if (_texture)
					_texture.dispose();

				_texture = context.createTexture(
					_width,
					_height,
					_format,
					_bitmapData == null && _atf == null
				);
			}

			if (_update)
			{
				_update = false;
				uploadBitmapDataWithMipMaps();
			}

			_atf = null;
			_bitmapData = null;

			return _texture;
		}

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

					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);
			}
		}

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

use string literals for texture formats to avoid compatibility issues