/*!
* CreateJS
* Visit http://createjs.com/ for documentation, updates and examples.
*
* Copyright (c) 2010 gskinner.com, inc.
*
* 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.
*/

this.createjs = this.createjs||{};


//##############################################################################
// extend.js
//##############################################################################

/**
 * @class Utility Methods
 */

/**
 * Sets up the prototype chain and constructor property for a new class.
 *
 * This should be called right after creating the class constructor.
 *
 *  function MySubClass() {}
 *  createjs.extend(MySubClass, MySuperClass);
 *  ClassB.prototype.doSomething = function() { }
 *
 *  var foo = new MySubClass();
 *  console.log(foo instanceof MySuperClass); // true
 *  console.log(foo.prototype.constructor === MySubClass); // true
 *
 * @method extend
 * @param {Function} subclass The subclass.
 * @param {Function} superclass The superclass to extend.
 * @return {Function} Returns the subclass's new prototype.
 */
createjs.extend = function(subclass, superclass) {
  "use strict";

  function o() { this.constructor = subclass; }
  o.prototype = superclass.prototype;
  return (subclass.prototype = new o());
};

//##############################################################################
// promote.js
//##############################################################################

/**
 * @class Utility Methods
 */

/**
 * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`.
 * It is recommended to use the super class's name as the prefix.
 * An alias to the super class's constructor is always added in the format `prefix_constructor`.
 * This allows the subclass to call super class methods without using `function.call`, providing better performance.
 *
 * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")`
 * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the
 * prototype of `MySubClass` as `MySuperClass_draw`.
 *
 * This should be called after the class's prototype is fully defined.
 *
 *  function ClassA(name) {
 *    this.name = name;
 *  }
 *  ClassA.prototype.greet = function() {
 *    return "Hello "+this.name;
 *  }
 *
 *  function ClassB(name, punctuation) {
 *    this.ClassA_constructor(name);
 *    this.punctuation = punctuation;
 *  }
 *  createjs.extend(ClassB, ClassA);
 *  ClassB.prototype.greet = function() {
 *    return this.ClassA_greet()+this.punctuation;
 *  }
 *  createjs.promote(ClassB, "ClassA");
 *
 *  var foo = new ClassB("World", "!?!");
 *  console.log(foo.greet()); // Hello World!?!
 *
 * @method promote
 * @param {Function} subclass The class to promote super class methods on.
 * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass.
 * @return {Function} Returns the subclass.
 */
createjs.promote = function(subclass, prefix) {
  "use strict";

  var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
  if (supP) {
    subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
    for (var n in supP) {
      if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; }
    }
  }
  return subclass;
};

//##############################################################################
// indexOf.js
//##############################################################################

/**
 * @class Utility Methods
 */

/**
 * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of
 * that value.  Returns -1 if value is not found.
 *
 *      var i = createjs.indexOf(myArray, myElementToFind);
 *
 * @method indexOf
 * @param {Array} array Array to search for searchElement
 * @param searchElement Element to find in array.
 * @return {Number} The first index of searchElement in array.
 */
createjs.indexOf = function (array, searchElement){
  "use strict";

  for (var i = 0,l=array.length; i < l; i++) {
    if (searchElement === array[i]) {
      return i;
    }
  }
  return -1;
};

//##############################################################################
// Event.js
//##############################################################################

(function() {
  "use strict";

// constructor:
  /**
   * Contains properties and methods shared by all events for use with
   * {{#crossLink "EventDispatcher"}}{{/crossLink}}.
   * 
   * Note that Event objects are often reused, so you should never
   * rely on an event object's state outside of the call stack it was received in.
   * @class Event
   * @param {String} type The event type.
   * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
   * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
   * @constructor
   **/
  function Event(type, bubbles, cancelable) {
    
  
  // public properties:
    /**
     * The type of event.
     * @property type
     * @type String
     **/
    this.type = type;
  
    /**
     * The object that generated an event.
     * @property target
     * @type Object
     * @default null
     * @readonly
    */
    this.target = null;
  
    /**
     * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
     * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
     * is generated from childObj, then a listener on parentObj would receive the event with
     * target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
     * @property currentTarget
     * @type Object
     * @default null
     * @readonly
    */
    this.currentTarget = null;
  
    /**
     * For bubbling events, this indicates the current event phase:<OL>
     *  <LI> capture phase: starting from the top parent to the target</LI>
     *  <LI> at target phase: currently being dispatched from the target</LI>
     *  <LI> bubbling phase: from the target to the top parent</LI>
     * </OL>
     * @property eventPhase
     * @type Number
     * @default 0
     * @readonly
    */
    this.eventPhase = 0;
  
    /**
     * Indicates whether the event will bubble through the display list.
     * @property bubbles
     * @type Boolean
     * @default false
     * @readonly
    */
    this.bubbles = !!bubbles;
  
    /**
     * Indicates whether the default behaviour of this event can be cancelled via
     * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
     * @property cancelable
     * @type Boolean
     * @default false
     * @readonly
    */
    this.cancelable = !!cancelable;
  
    /**
     * The epoch time at which this event was created.
     * @property timeStamp
     * @type Number
     * @default 0
     * @readonly
    */
    this.timeStamp = (new Date()).getTime();
  
    /**
     * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
     * on this event.
     * @property defaultPrevented
     * @type Boolean
     * @default false
     * @readonly
    */
    this.defaultPrevented = false;
  
    /**
     * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
     * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
     * @property propagationStopped
     * @type Boolean
     * @default false
     * @readonly
    */
    this.propagationStopped = false;
  
    /**
     * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
     * on this event.
     * @property immediatePropagationStopped
     * @type Boolean
     * @default false
     * @readonly
    */
    this.immediatePropagationStopped = false;
    
    /**
     * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
     * @property removed
     * @type Boolean
     * @default false
     * @readonly
    */
    this.removed = false;
  }
  var p = Event.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.

// public methods:
  /**
   * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable.
   * Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will
   * cancel the default behaviour associated with the event.
   * @method preventDefault
   **/
  p.preventDefault = function() {
    this.defaultPrevented = this.cancelable&&true;
  };

  /**
   * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
   * Mirrors the DOM event standard.
   * @method stopPropagation
   **/
  p.stopPropagation = function() {
    this.propagationStopped = true;
  };

  /**
   * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
   * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
   * Mirrors the DOM event standard.
   * @method stopImmediatePropagation
   **/
  p.stopImmediatePropagation = function() {
    this.immediatePropagationStopped = this.propagationStopped = true;
  };
  
  /**
   * Causes the active listener to be removed via removeEventListener();
   * 
   *    myBtn.addEventListener("click", function(evt) {
   *      // do stuff...
   *      evt.remove(); // removes this listener.
   *    });
   * 
   * @method remove
   **/
  p.remove = function() {
    this.removed = true;
  };
  
  /**
   * Returns a clone of the Event instance.
   * @method clone
   * @return {Event} a clone of the Event instance.
   **/
  p.clone = function() {
    return new Event(this.type, this.bubbles, this.cancelable);
  };
  
  /**
   * Provides a chainable shortcut method for setting a number of properties on the instance.
   *
   * @method set
   * @param {Object} props A generic object containing properties to copy to the instance.
   * @return {Event} Returns the instance the method is called on (useful for chaining calls.)
   * @chainable
  */
  p.set = function(props) {
    for (var n in props) { this[n] = props[n]; }
    return this;
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Event (type="+this.type+")]";
  };

  createjs.Event = Event;
}());

//##############################################################################
// EventDispatcher.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * EventDispatcher provides methods for managing queues of event listeners and dispatching events.
   *
   * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
   * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
   * 
   * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
   * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
   * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
   * 
   * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
   * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The 
   * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
   * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
   * 
   * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
   * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also 
   * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
   *
   * <h4>Example</h4>
   * Add EventDispatcher capabilities to the "MyClass" class.
   *
   *      EventDispatcher.initialize(MyClass.prototype);
   *
   * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}).
   *
   *      instance.addEventListener("eventName", handlerMethod);
   *      function handlerMethod(event) {
   *          console.log(event.target + " Was Clicked");
   *      }
   *
   * <b>Maintaining proper scope</b><br />
   * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}}
   * method to subscribe to events simplifies this.
   *
   *      instance.addEventListener("click", function(event) {
   *          console.log(instance == this); // false, scope is ambiguous.
   *      });
   *      
   *      instance.on("click", function(event) {
   *          console.log(instance == this); // true, "on" uses dispatcher scope by default.
   *      });
   * 
   * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope.
   *      
   *
   * @class EventDispatcher
   * @constructor
   **/
  function EventDispatcher() {
  
  
  // private properties:
    /**
     * @protected
     * @property _listeners
     * @type Object
     **/
    this._listeners = null;
    
    /**
     * @protected
     * @property _captureListeners
     * @type Object
     **/
    this._captureListeners = null;
  }
  var p = EventDispatcher.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// static public methods:
  /**
   * Static initializer to mix EventDispatcher methods into a target object or prototype.
   * 
   *    EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
   *    EventDispatcher.initialize(myObject); // add to a specific instance
   * 
   * @method initialize
   * @static
   * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
   * prototype.
   **/
  EventDispatcher.initialize = function(target) {
    target.addEventListener = p.addEventListener;
    target.on = p.on;
    target.removeEventListener = target.off =  p.removeEventListener;
    target.removeAllEventListeners = p.removeAllEventListeners;
    target.hasEventListener = p.hasEventListener;
    target.dispatchEvent = p.dispatchEvent;
    target._dispatchEvent = p._dispatchEvent;
    target.willTrigger = p.willTrigger;
  };
  

// public methods:
  /**
   * Adds the specified event listener. Note that adding multiple listeners to the same function will result in
   * multiple callbacks getting fired.
   *
   * <h4>Example</h4>
   *
   *      displayObject.addEventListener("click", handleClick);
   *      function handleClick(event) {
   *         // Click happened.
   *      }
   *
   * @method addEventListener
   * @param {String} type The string type of the event.
   * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
   * the event is dispatched.
   * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
   * @return {Function | Object} Returns the listener for chaining or assignment.
   **/
  p.addEventListener = function(type, listener, useCapture) {
    var listeners;
    if (useCapture) {
      listeners = this._captureListeners = this._captureListeners||{};
    } else {
      listeners = this._listeners = this._listeners||{};
    }
    var arr = listeners[type];
    if (arr) { this.removeEventListener(type, listener, useCapture); }
    arr = listeners[type]; // remove may have deleted the array
    if (!arr) { listeners[type] = [listener];  }
    else { arr.push(listener); }
    return listener;
  };
  
  /**
   * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
   * only run once, associate arbitrary data with the listener, and remove the listener.
   * 
   * This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
   * The wrapper function is returned for use with `removeEventListener` (or `off`).
   * 
   * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener, or use
   * {{#crossLink "Event/remove"}}{{/crossLink}}. Likewise, each time you call `on` a NEW wrapper function is subscribed, so multiple calls
   * to `on` with the same params will create multiple listeners.
   * 
   * <h4>Example</h4>
   * 
   *    var listener = myBtn.on("click", handleClick, null, false, {count:3});
   *    function handleClick(evt, data) {
   *      data.count -= 1;
   *      console.log(this == myBtn); // true - scope defaults to the dispatcher
   *      if (data.count == 0) {
   *        alert("clicked 3 times!");
   *        myBtn.off("click", listener);
   *        // alternately: evt.remove();
   *      }
   *    }
   * 
   * @method on
   * @param {String} type The string type of the event.
   * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
   * the event is dispatched.
   * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent).
   * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered.
   * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called.
   * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
   * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener.
   **/
  p.on = function(type, listener, scope, once, data, useCapture) {
    if (listener.handleEvent) {
      scope = scope||listener;
      listener = listener.handleEvent;
    }
    scope = scope||this;
    return this.addEventListener(type, function(evt) {
        listener.call(scope, evt, data);
        once&&evt.remove();
      }, useCapture);
  };

  /**
   * Removes the specified event listener.
   *
   * <b>Important Note:</b> that you must pass the exact function reference used when the event was added. If a proxy
   * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or
   * closure will not work.
   *
   * <h4>Example</h4>
   *
   *      displayObject.removeEventListener("click", handleClick);
   *
   * @method removeEventListener
   * @param {String} type The string type of the event.
   * @param {Function | Object} listener The listener function or object.
   * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
   **/
  p.removeEventListener = function(type, listener, useCapture) {
    var listeners = useCapture ? this._captureListeners : this._listeners;
    if (!listeners) { return; }
    var arr = listeners[type];
    if (!arr) { return; }
    for (var i=0,l=arr.length; i<l; i++) {
      if (arr[i] == listener) {
        if (l==1) { delete(listeners[type]); } // allows for faster checks.
        else { arr.splice(i,1); }
        break;
      }
    }
  };
  
  /**
   * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
   * .on method.
   * 
   * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See 
   * {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example.
   *
   * @method off
   * @param {String} type The string type of the event.
   * @param {Function | Object} listener The listener function or object.
   * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
   **/
  p.off = p.removeEventListener;

  /**
   * Removes all listeners for the specified type, or all listeners of all types.
   *
   * <h4>Example</h4>
   *
   *      // Remove all listeners
   *      displayObject.removeAllEventListeners();
   *
   *      // Remove all click listeners
   *      displayObject.removeAllEventListeners("click");
   *
   * @method removeAllEventListeners
   * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed.
   **/
  p.removeAllEventListeners = function(type) {
    if (!type) { this._listeners = this._captureListeners = null; }
    else {
      if (this._listeners) { delete(this._listeners[type]); }
      if (this._captureListeners) { delete(this._captureListeners[type]); }
    }
  };

  /**
   * Dispatches the specified event to all listeners.
   *
   * <h4>Example</h4>
   *
   *      // Use a string event
   *      this.dispatchEvent("complete");
   *
   *      // Use an Event instance
   *      var event = new createjs.Event("progress");
   *      this.dispatchEvent(event);
   *
   * @method dispatchEvent
   * @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
   * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
   * dispatchEvent will construct an Event instance if necessary with the specified type. This latter approach can
   * be used to avoid event object instantiation for non-bubbling events that may not have any listeners.
   * @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj.
   * @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj.
   * @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise.
   **/
  p.dispatchEvent = function(eventObj, bubbles, cancelable) {
    if (typeof eventObj == "string") {
      // skip everything if there's no listeners and it doesn't bubble:
      var listeners = this._listeners;
      if (!bubbles && (!listeners || !listeners[eventObj])) { return true; }
      eventObj = new createjs.Event(eventObj, bubbles, cancelable);
    } else if (eventObj.target && eventObj.clone) {
      // redispatching an active event object, so clone it:
      eventObj = eventObj.clone();
    }
    
    // TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent
    try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events

    if (!eventObj.bubbles || !this.parent) {
      this._dispatchEvent(eventObj, 2);
    } else {
      var top=this, list=[top];
      while (top.parent) { list.push(top = top.parent); }
      var i, l=list.length;

      // capture & atTarget
      for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) {
        list[i]._dispatchEvent(eventObj, 1+(i==0));
      }
      // bubbling
      for (i=1; i<l && !eventObj.propagationStopped; i++) {
        list[i]._dispatchEvent(eventObj, 3);
      }
    }
    return !eventObj.defaultPrevented;
  };

  /**
   * Indicates whether there is at least one listener for the specified event type.
   * @method hasEventListener
   * @param {String} type The string type of the event.
   * @return {Boolean} Returns true if there is at least one listener for the specified event.
   **/
  p.hasEventListener = function(type) {
    var listeners = this._listeners, captureListeners = this._captureListeners;
    return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
  };
  
  /**
   * Indicates whether there is at least one listener for the specified event type on this object or any of its
   * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
   * specified type is dispatched from this object, it will trigger at least one listener.
   * 
   * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
   * event flow for a listener, not just this object.
   * @method willTrigger
   * @param {String} type The string type of the event.
   * @return {Boolean} Returns `true` if there is at least one listener for the specified event.
   **/
  p.willTrigger = function(type) {
    var o = this;
    while (o) {
      if (o.hasEventListener(type)) { return true; }
      o = o.parent;
    }
    return false;
  };

  /**
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[EventDispatcher]";
  };


// private methods:
  /**
   * @method _dispatchEvent
   * @param {Object | String | Event} eventObj
   * @param {Object} eventPhase
   * @protected
   **/
  p._dispatchEvent = function(eventObj, eventPhase) {
    var l, listeners = (eventPhase==1) ? this._captureListeners : this._listeners;
    if (eventObj && listeners) {
      var arr = listeners[eventObj.type];
      if (!arr||!(l=arr.length)) { return; }
      try { eventObj.currentTarget = this; } catch (e) {}
      try { eventObj.eventPhase = eventPhase; } catch (e) {}
      eventObj.removed = false;
      
      arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
      for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) {
        var o = arr[i];
        if (o.handleEvent) { o.handleEvent(eventObj); }
        else { o(eventObj); }
        if (eventObj.removed) {
          this.off(eventObj.type, o, eventPhase==1);
          eventObj.removed = false;
        }
      }
    }
  };


  createjs.EventDispatcher = EventDispatcher;
}());

//##############################################################################
// Ticker.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick
   * event to be notified when a set time interval has elapsed.
   *
   * Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval
   * when under high CPU load. The Ticker class uses a static interface (ex. `Ticker.framerate = 30;`) and
   * can not be instantiated.
   *
   * <h4>Example</h4>
   *
   *      createjs.Ticker.addEventListener("tick", handleTick);
   *      function handleTick(event) {
   *          // Actions carried out each tick (aka frame)
   *          if (!event.paused) {
   *              // Actions carried out when the Ticker is not paused.
   *          }
   *      }
   *
   * @class Ticker
   * @uses EventDispatcher
   * @static
   **/
  function Ticker() {
    throw "Ticker cannot be instantiated.";
  }


// constants:
  /**
   * In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It
   * uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and
   * dispatches the tick when the time is within a certain threshold.
   *
   * This mode has a higher variance for time between frames than {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}},
   * but does not require that content be time based as with {{#crossLink "Ticker/RAF:property"}}{{/crossLink}} while
   * gaining the benefits of that API (screen synch, background throttling).
   *
   * Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so
   * framerates of 10, 12, 15, 20, and 30 work well.
   *
   * Falls back to {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not
   * supported.
   * @property RAF_SYNCHED
   * @static
   * @type {String}
   * @default "synched"
   * @readonly
   **/
  Ticker.RAF_SYNCHED = "synched";

  /**
   * In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely.
   * Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based.
   * You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the {{#crossLink "Ticker/tick:event"}}{{/crossLink}}
   * event object's "delta" properties to make this easier.
   *
   * Falls back on {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not
   * supported.
   * @property RAF
   * @static
   * @type {String}
   * @default "raf"
   * @readonly
   **/
  Ticker.RAF = "raf";

  /**
   * In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not
   * provide the benefits of requestAnimationFrame (screen synch, background throttling).
   * @property TIMEOUT
   * @static
   * @type {String}
   * @default "timeout"
   * @readonly
   **/
  Ticker.TIMEOUT = "timeout";


// static events:
  /**
   * Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using
   * {{#crossLink "Ticker/setPaused"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *      createjs.Ticker.addEventListener("tick", handleTick);
   *      function handleTick(event) {
   *          console.log("Paused:", event.paused, event.delta);
   *      }
   *
   * @event tick
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {Boolean} paused Indicates whether the ticker is currently paused.
   * @param {Number} delta The time elapsed in ms since the last tick.
   * @param {Number} time The total time in ms since Ticker was initialized.
   * @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example,
   *  you could determine the amount of time that the Ticker has been paused since initialization with `time-runTime`.
   * @since 0.6.0
   */


// public static properties:
  /**
   * Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will
   * use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default.
   * @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}.
   * @property useRAF
   * @static
   * @type {Boolean}
   * @default false
   **/
  Ticker.useRAF = false;

  /**
   * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See
   * {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and
   * {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details.
   * @property timingMode
   * @static
   * @type {String}
   * @default Ticker.TIMEOUT
   **/
  Ticker.timingMode = null;

  /**
   * Specifies a maximum value for the delta property in the tick event object. This is useful when building time
   * based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep,
   * alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value
   * (ex. maxDelta=50 when running at 40fps).
   * 
   * This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta
   * when using both delta and other values.
   * 
   * If 0, there is no maximum.
   * @property maxDelta
   * @static
   * @type {number}
   * @default 0
   */
  Ticker.maxDelta = 0;
  
  /**
   * When the ticker is paused, all listeners will still receive a tick event, but the <code>paused</code> property
   * of the event will be `true`. Also, while paused the `runTime` will not increase. See {{#crossLink "Ticker/tick:event"}}{{/crossLink}},
   * {{#crossLink "Ticker/getTime"}}{{/crossLink}}, and {{#crossLink "Ticker/getEventTime"}}{{/crossLink}} for more
   * info.
   *
   * <h4>Example</h4>
   *
   *      createjs.Ticker.addEventListener("tick", handleTick);
   *      createjs.Ticker.paused = true;
   *      function handleTick(event) {
   *          console.log(event.paused,
   *            createjs.Ticker.getTime(false),
   *            createjs.Ticker.getTime(true));
   *      }
   *
   * @property paused
   * @static
   * @type {Boolean}
   * @default false
   **/
  Ticker.paused = false;


// mix-ins:
  // EventDispatcher methods:
  Ticker.removeEventListener = null;
  Ticker.removeAllEventListeners = null;
  Ticker.dispatchEvent = null;
  Ticker.hasEventListener = null;
  Ticker._listeners = null;
  createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods.
  Ticker._addEventListener = Ticker.addEventListener;
  Ticker.addEventListener = function() {
    !Ticker._inited&&Ticker.init();
    return Ticker._addEventListener.apply(Ticker, arguments);
  };


// private static properties:
  /**
   * @property _inited
   * @static
   * @type {Boolean}
   * @protected
   **/
  Ticker._inited = false;

  /**
   * @property _startTime
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._startTime = 0;

  /**
   * @property _pausedTime
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._pausedTime=0;

  /**
   * The number of ticks that have passed
   * @property _ticks
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._ticks = 0;

  /**
   * The number of ticks that have passed while Ticker has been paused
   * @property _pausedTicks
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._pausedTicks = 0;

  /**
   * @property _interval
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._interval = 50;

  /**
   * @property _lastTime
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._lastTime = 0;

  /**
   * @property _times
   * @static
   * @type {Array}
   * @protected
   **/
  Ticker._times = null;

  /**
   * @property _tickTimes
   * @static
   * @type {Array}
   * @protected
   **/
  Ticker._tickTimes = null;

  /**
   * Stores the timeout or requestAnimationFrame id.
   * @property _timerId
   * @static
   * @type {Number}
   * @protected
   **/
  Ticker._timerId = null;
  
  /**
   * True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode
   * if that property changed and a tick hasn't fired.
   * @property _raf
   * @static
   * @type {Boolean}
   * @protected
   **/
  Ticker._raf = true;
  

// static getter / setters:
  /**
   * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead.
   * @method setInterval
   * @static
   * @param {Number} interval
   * @deprecated
   **/
  Ticker.setInterval = function(interval) {
    Ticker._interval = interval;
    if (!Ticker._inited) { return; }
    Ticker._setupTick();
  };

  /**
   * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead.
   * @method getInterval
   * @static
   * @return {Number}
   * @deprecated
   **/
  Ticker.getInterval = function() {
    return Ticker._interval;
  };

  /**
   * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead.
   * @method setFPS
   * @static
   * @param {Number} value
   * @deprecated
   **/
  Ticker.setFPS = function(value) {
    Ticker.setInterval(1000/value);
  };

  /**
   * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead.
   * @method getFPS
   * @static
   * @return {Number}
   * @deprecated
   **/
  Ticker.getFPS = function() {
    return 1000/Ticker._interval;
  };

  /**
   * Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS).
   * Note that actual time between ticks may be more than specified depending on CPU load.
   * This property is ignored if the ticker is using the `RAF` timing mode.
   * @property interval
   * @static
   * @type {Number}
   **/
   
  /**
   * Indicates the target frame rate in frames per second (FPS). Effectively just a shortcut to `interval`, where
   * `framerate == 1000/interval`.
   * @property framerate
   * @static
   * @type {Number}
   **/
  try {
    Object.defineProperties(Ticker, {
      interval: { get: Ticker.getInterval, set: Ticker.setInterval },
      framerate: { get: Ticker.getFPS, set: Ticker.setFPS }
    });
  } catch (e) { console.log(e); }


// public static methods:
  /**
   * Starts the tick. This is called automatically when the first listener is added.
   * @method init
   * @static
   **/
  Ticker.init = function() {
    if (Ticker._inited) { return; }
    Ticker._inited = true;
    Ticker._times = [];
    Ticker._tickTimes = [];
    Ticker._startTime = Ticker._getTime();
    Ticker._times.push(Ticker._lastTime = 0);
    Ticker.interval = Ticker._interval;
  };
  
  /**
   * Stops the Ticker and removes all listeners. Use init() to restart the Ticker.
   * @method reset
   * @static
   **/
  Ticker.reset = function() {
    if (Ticker._raf) {
      var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame;
      f&&f(Ticker._timerId);
    } else {
      clearTimeout(Ticker._timerId);
    }
    Ticker.removeAllEventListeners("tick");
    Ticker._timerId = Ticker._times = Ticker._tickTimes = null;
    Ticker._startTime = Ticker._lastTime = Ticker._ticks = 0;
    Ticker._inited = false;
  };

  /**
   * Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS
   * because it only measures the time spent within the tick execution stack. 
   * 
   * Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between 
   * the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that 
   * there may be up to 35ms of "idle" time between the end of one tick and the start of the next.
   *
   * Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of
   * one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something
   * other than the tick is using ~80ms (another script, DOM rendering, etc).
   * @method getMeasuredTickTime
   * @static
   * @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick.
   * Defaults to the number of ticks per second. To get only the last tick's time, pass in 1.
   * @return {Number} The average time spent in a tick in milliseconds.
   **/
  Ticker.getMeasuredTickTime = function(ticks) {
    var ttl=0, times=Ticker._tickTimes;
    if (!times || times.length < 1) { return -1; }

    // by default, calculate average for the past ~1 second:
    ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0));
    for (var i=0; i<ticks; i++) { ttl += times[i]; }
    return ttl/ticks;
  };

  /**
   * Returns the actual frames / ticks per second.
   * @method getMeasuredFPS
   * @static
   * @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second.
   * Defaults to the number of ticks per second.
   * @return {Number} The actual frames / ticks per second. Depending on performance, this may differ
   * from the target frames per second.
   **/
  Ticker.getMeasuredFPS = function(ticks) {
    var times = Ticker._times;
    if (!times || times.length < 2) { return -1; }

    // by default, calculate fps for the past ~1 second:
    ticks = Math.min(times.length-1, ticks||(Ticker.getFPS()|0));
    return 1000/((times[0]-times[ticks])/ticks);
  };

  /**
   * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead.
   * @method setPaused
   * @static
   * @param {Boolean} value
   * @deprecated
   **/
  Ticker.setPaused = function(value) {
    // TODO: deprecated.
    Ticker.paused = value;
  };

  /**
   * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead.
   * @method getPaused
   * @static
   * @return {Boolean}
   * @deprecated
   **/
  Ticker.getPaused = function() {
    // TODO: deprecated.
    return Ticker.paused;
  };

  /**
   * Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}.
   * Returns -1 if Ticker has not been initialized. For example, you could use
   * this in a time synchronized animation to determine the exact amount of time that has elapsed.
   * @method getTime
   * @static
   * @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned.
   * If false, the value returned will be total time elapsed since the first tick event listener was added.
   * @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1.
   **/
  Ticker.getTime = function(runTime) {
    return Ticker._startTime ? Ticker._getTime() - (runTime ? Ticker._pausedTime : 0) : -1;
  };

  /**
   * Similar to the {{#crossLink "Ticker/getTime"}}{{/crossLink}} method, but returns the time on the most recent {{#crossLink "Ticker/tick:event"}}{{/crossLink}}
   * event object.
   * @method getEventTime
   * @static
   * @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time.
   * @returns {number} The time or runTime property from the most recent tick event or -1.
   */
  Ticker.getEventTime = function(runTime) {
    return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1;
  };
  
  /**
   * Returns the number of ticks that have been broadcast by Ticker.
   * @method getTicks
   * @static
   * @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast
   * while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned.
   * If false, tick events that would have been broadcast while Ticker was paused will be included in the return
   * value. The default value is false.
   * @return {Number} of ticks that have been broadcast.
   **/
  Ticker.getTicks = function(pauseable) {
    return  Ticker._ticks - (pauseable ? Ticker._pausedTicks : 0);
  };


// private static methods:
  /**
   * @method _handleSynch
   * @static
   * @protected
   **/
  Ticker._handleSynch = function() {
    Ticker._timerId = null;
    Ticker._setupTick();

    // run if enough time has elapsed, with a little bit of flexibility to be early:
    if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval-1)*0.97) {
      Ticker._tick();
    }
  };

  /**
   * @method _handleRAF
   * @static
   * @protected
   **/
  Ticker._handleRAF = function() {
    Ticker._timerId = null;
    Ticker._setupTick();
    Ticker._tick();
  };

  /**
   * @method _handleTimeout
   * @static
   * @protected
   **/
  Ticker._handleTimeout = function() {
    Ticker._timerId = null;
    Ticker._setupTick();
    Ticker._tick();
  };

  /**
   * @method _setupTick
   * @static
   * @protected
   **/
  Ticker._setupTick = function() {
    if (Ticker._timerId != null) { return; } // avoid duplicates

    var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED);
    if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) {
      var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame;
      if (f) {
        Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch);
        Ticker._raf = true;
        return;
      }
    }
    Ticker._raf = false;
    Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval);
  };

  /**
   * @method _tick
   * @static
   * @protected
   **/
  Ticker._tick = function() {
    var paused = Ticker.paused;
    var time = Ticker._getTime();
    var elapsedTime = time-Ticker._lastTime;
    Ticker._lastTime = time;
    Ticker._ticks++;
    
    if (paused) {
      Ticker._pausedTicks++;
      Ticker._pausedTime += elapsedTime;
    }
    
    if (Ticker.hasEventListener("tick")) {
      var event = new createjs.Event("tick");
      var maxDelta = Ticker.maxDelta;
      event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime;
      event.paused = paused;
      event.time = time;
      event.runTime = time-Ticker._pausedTime;
      Ticker.dispatchEvent(event);
    }
    
    Ticker._tickTimes.unshift(Ticker._getTime()-time);
    while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); }

    Ticker._times.unshift(time);
    while (Ticker._times.length > 100) { Ticker._times.pop(); }
  };

  /**
   * @method _getTime
   * @static
   * @protected
   **/
  var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow);
  Ticker._getTime = function() {
    return ((now&&now.call(performance))||(new Date().getTime())) - Ticker._startTime;
  };


  createjs.Ticker = Ticker;
}());

//##############################################################################
// UID.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Global utility for generating sequential unique ID numbers. The UID class uses a static interface (ex. <code>UID.get()</code>)
   * and should not be instantiated.
   * @class UID
   * @static
   **/
  function UID() {
    throw "UID cannot be instantiated";
  }


// private static properties:
  /**
   * @property _nextID
   * @type Number
   * @protected
   **/
  UID._nextID = 0;


// public static methods:
  /**
   * Returns the next unique id.
   * @method get
   * @return {Number} The next unique id
   * @static
   **/
  UID.get = function() {
    return UID._nextID++;
  };


  createjs.UID = UID;
}());

//##############################################################################
// MouseEvent.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Passed as the parameter to all mouse/pointer/touch related events. For a listing of mouse events and their properties,
   * see the {{#crossLink "DisplayObject"}}{{/crossLink}} and {{#crossLink "Stage"}}{{/crossLink}} event listings.
   * @class MouseEvent
   * @param {String} type The event type.
   * @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
   * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
   * @param {Number} stageX The normalized x position relative to the stage.
   * @param {Number} stageY The normalized y position relative to the stage.
   * @param {MouseEvent} nativeEvent The native DOM event related to this mouse event.
   * @param {Number} pointerID The unique id for the pointer.
   * @param {Boolean} primary Indicates whether this is the primary pointer in a multitouch environment.
   * @param {Number} rawX The raw x position relative to the stage.
   * @param {Number} rawY The raw y position relative to the stage.
   * @param {DisplayObject} relatedTarget The secondary target for the event.
   * @extends Event
   * @constructor
   **/
  function MouseEvent(type, bubbles, cancelable, stageX, stageY, nativeEvent, pointerID, primary, rawX, rawY, relatedTarget) {
    this.Event_constructor(type, bubbles, cancelable);
    
    
  // public properties:
    /**
     * The normalized x position on the stage. This will always be within the range 0 to stage width.
     * @property stageX
     * @type Number
    */
    this.stageX = stageX;
  
    /**
     * The normalized y position on the stage. This will always be within the range 0 to stage height.
     * @property stageY
     * @type Number
     **/
    this.stageY = stageY;
  
    /**
     * The raw x position relative to the stage. Normally this will be the same as the stageX value, unless
     * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds.
     * @property rawX
     * @type Number
    */
    this.rawX = (rawX==null)?stageX:rawX;
  
    /**
     * The raw y position relative to the stage. Normally this will be the same as the stageY value, unless
     * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds.
     * @property rawY
     * @type Number
    */
    this.rawY = (rawY==null)?stageY:rawY;
  
    /**
     * The native MouseEvent generated by the browser. The properties and API for this
     * event may differ between browsers. This property will be null if the
     * EaselJS property was not directly generated from a native MouseEvent.
     * @property nativeEvent
     * @type HtmlMouseEvent
     * @default null
     **/
    this.nativeEvent = nativeEvent;
  
    /**
     * The unique id for the pointer (touch point or cursor). This will be either -1 for the mouse, or the system
     * supplied id value.
     * @property pointerID
     * @type {Number}
     */
    this.pointerID = pointerID;
  
    /**
     * Indicates whether this is the primary pointer in a multitouch environment. This will always be true for the mouse.
     * For touch pointers, the first pointer in the current stack will be considered the primary pointer.
     * @property primary
     * @type {Boolean}
     */
    this.primary = !!primary;
    
    /**
     * The secondary target for the event, if applicable. This is used for mouseout/rollout
     * events to indicate the object that the mouse entered from, mouseover/rollover for the object the mouse exited,
     * and stagemousedown/stagemouseup events for the object that was the under the cursor, if any.
     * 
     * Only valid interaction targets will be returned (ie. objects with mouse listeners or a cursor set).
     * @property relatedTarget
     * @type {DisplayObject}
     */
    this.relatedTarget = relatedTarget;
  }
  var p = createjs.extend(MouseEvent, createjs.Event);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
  
  
// getter / setters:
  /**
   * Returns the x position of the mouse in the local coordinate system of the current target (ie. the dispatcher).
   * @property localX
   * @type {Number}
   * @readonly
   */
  p._get_localX = function() {
    return this.currentTarget.globalToLocal(this.rawX, this.rawY).x;
  };
  
  /**
   * Returns the y position of the mouse in the local coordinate system of the current target (ie. the dispatcher).
   * @property localY
   * @type {Number}
   * @readonly
   */
  p._get_localY = function() {
    return this.currentTarget.globalToLocal(this.rawX, this.rawY).y;
  };
  
  /**
   * Indicates whether the event was generated by a touch input (versus a mouse input).
   * @property isTouch
   * @type {Boolean}
   * @readonly
   */
  p._get_isTouch = function() {
    return this.pointerID !== -1;
  };
  
  
  try {
    Object.defineProperties(p, {
      localX: { get: p._get_localX },
      localY: { get: p._get_localY },
      isTouch: { get: p._get_isTouch }
    });
  } catch (e) {} // TODO: use Log


// public methods:
  /**
   * Returns a clone of the MouseEvent instance.
   * @method clone
   * @return {MouseEvent} a clone of the MouseEvent instance.
   **/
  p.clone = function() {
    return new MouseEvent(this.type, this.bubbles, this.cancelable, this.stageX, this.stageY, this.nativeEvent, this.pointerID, this.primary, this.rawX, this.rawY);
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]";
  };


  createjs.MouseEvent = createjs.promote(MouseEvent, "Event");
}());

//##############################################################################
// Matrix2D.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices.
   *
   * This matrix can be visualized as:
   *
   *  [ a  c  tx
   *    b  d  ty
   *    0  0  1  ]
   *
   * Note the locations of b and c.
   *
   * @class Matrix2D
   * @param {Number} [a=1] Specifies the a property for the new matrix.
   * @param {Number} [b=0] Specifies the b property for the new matrix.
   * @param {Number} [c=0] Specifies the c property for the new matrix.
   * @param {Number} [d=1] Specifies the d property for the new matrix.
   * @param {Number} [tx=0] Specifies the tx property for the new matrix.
   * @param {Number} [ty=0] Specifies the ty property for the new matrix.
   * @constructor
   **/
  function Matrix2D(a, b, c, d, tx, ty) {
    this.setValues(a,b,c,d,tx,ty);
    
  // public properties:
    // assigned in the setValues method.
    /**
     * Position (0, 0) in a 3x3 affine transformation matrix.
     * @property a
     * @type Number
     **/
  
    /**
     * Position (0, 1) in a 3x3 affine transformation matrix.
     * @property b
     * @type Number
     **/
  
    /**
     * Position (1, 0) in a 3x3 affine transformation matrix.
     * @property c
     * @type Number
     **/
  
    /**
     * Position (1, 1) in a 3x3 affine transformation matrix.
     * @property d
     * @type Number
     **/
  
    /**
     * Position (2, 0) in a 3x3 affine transformation matrix.
     * @property tx
     * @type Number
     **/
  
    /**
     * Position (2, 1) in a 3x3 affine transformation matrix.
     * @property ty
     * @type Number
     **/
  }
  var p = Matrix2D.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// constants:
  /**
   * Multiplier for converting degrees to radians. Used internally by Matrix2D.
   * @property DEG_TO_RAD
   * @static
   * @final
   * @type Number
   * @readonly
   **/
  Matrix2D.DEG_TO_RAD = Math.PI/180;


// static public properties:
  /**
   * An identity matrix, representing a null transformation.
   * @property identity
   * @static
   * @type Matrix2D
   * @readonly
   **/
  Matrix2D.identity = null; // set at bottom of class definition.
  

// public methods:
  /**
   * Sets the specified values on this instance. 
   * @method setValues
   * @param {Number} [a=1] Specifies the a property for the new matrix.
   * @param {Number} [b=0] Specifies the b property for the new matrix.
   * @param {Number} [c=0] Specifies the c property for the new matrix.
   * @param {Number} [d=1] Specifies the d property for the new matrix.
   * @param {Number} [tx=0] Specifies the tx property for the new matrix.
   * @param {Number} [ty=0] Specifies the ty property for the new matrix.
   * @return {Matrix2D} This instance. Useful for chaining method calls.
  */
  p.setValues = function(a, b, c, d, tx, ty) {
    // don't forget to update docs in the constructor if these change:
    this.a = (a == null) ? 1 : a;
    this.b = b || 0;
    this.c = c || 0;
    this.d = (d == null) ? 1 : d;
    this.tx = tx || 0;
    this.ty = ty || 0;
    return this;
  };

  /**
   * Appends the specified matrix properties to this matrix. All parameters are required.
   * This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
   * @method append
   * @param {Number} a
   * @param {Number} b
   * @param {Number} c
   * @param {Number} d
   * @param {Number} tx
   * @param {Number} ty
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.append = function(a, b, c, d, tx, ty) {
    var a1 = this.a;
    var b1 = this.b;
    var c1 = this.c;
    var d1 = this.d;
    if (a != 1 || b != 0 || c != 0 || d != 1) {
      this.a  = a1*a+c1*b;
      this.b  = b1*a+d1*b;
      this.c  = a1*c+c1*d;
      this.d  = b1*c+d1*d;
    }
    this.tx = a1*tx+c1*ty+this.tx;
    this.ty = b1*tx+d1*ty+this.ty;
    return this;
  };

  /**
   * Prepends the specified matrix properties to this matrix.
   * This is the equivalent of multiplying `(specified matrix) * (this matrix)`.
   * All parameters are required.
   * @method prepend
   * @param {Number} a
   * @param {Number} b
   * @param {Number} c
   * @param {Number} d
   * @param {Number} tx
   * @param {Number} ty
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.prepend = function(a, b, c, d, tx, ty) {
    var a1 = this.a;
    var c1 = this.c;
    var tx1 = this.tx;

    this.a  = a*a1+c*this.b;
    this.b  = b*a1+d*this.b;
    this.c  = a*c1+c*this.d;
    this.d  = b*c1+d*this.d;
    this.tx = a*tx1+c*this.ty+tx;
    this.ty = b*tx1+d*this.ty+ty;
    return this;
  };

  /**
   * Appends the specified matrix to this matrix.
   * This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
   * @method appendMatrix
   * @param {Matrix2D} matrix
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.appendMatrix = function(matrix) {
    return this.append(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
  };

  /**
   * Prepends the specified matrix to this matrix.
   * This is the equivalent of multiplying `(specified matrix) * (this matrix)`.
   * For example, you could calculate the combined transformation for a child object using:
   * 
   *  var o = myDisplayObject;
   *  var mtx = o.getMatrix();
   *  while (o = o.parent) {
   *    // prepend each parent's transformation in turn:
   *    o.prependMatrix(o.getMatrix());
   *  }
   * @method prependMatrix
   * @param {Matrix2D} matrix
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.prependMatrix = function(matrix) {
    return this.prepend(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
  };

  /**
   * Generates matrix properties from the specified display object transform properties, and appends them to this matrix.
   * For example, you can use this to generate a matrix representing the transformations of a display object:
   * 
   *  var mtx = new Matrix2D();
   *  mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation);
   * @method appendTransform
   * @param {Number} x
   * @param {Number} y
   * @param {Number} scaleX
   * @param {Number} scaleY
   * @param {Number} rotation
   * @param {Number} skewX
   * @param {Number} skewY
   * @param {Number} regX Optional.
   * @param {Number} regY Optional.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
    if (rotation%360) {
      var r = rotation*Matrix2D.DEG_TO_RAD;
      var cos = Math.cos(r);
      var sin = Math.sin(r);
    } else {
      cos = 1;
      sin = 0;
    }

    if (skewX || skewY) {
      // TODO: can this be combined into a single append operation?
      skewX *= Matrix2D.DEG_TO_RAD;
      skewY *= Matrix2D.DEG_TO_RAD;
      this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y);
      this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0);
    } else {
      this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y);
    }
    
    if (regX || regY) {
      // append the registration offset:
      this.tx -= regX*this.a+regY*this.c; 
      this.ty -= regX*this.b+regY*this.d;
    }
    return this;
  };

  /**
   * Generates matrix properties from the specified display object transform properties, and prepends them to this matrix.
   * For example, you could calculate the combined transformation for a child object using:
   * 
   *  var o = myDisplayObject;
   *  var mtx = new createjs.Matrix2D();
   *  do  {
   *    // prepend each parent's transformation in turn:
   *    mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY);
   *  } while (o = o.parent);
   *  
   *  Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}}
   *  values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does.
   * @method prependTransform
   * @param {Number} x
   * @param {Number} y
   * @param {Number} scaleX
   * @param {Number} scaleY
   * @param {Number} rotation
   * @param {Number} skewX
   * @param {Number} skewY
   * @param {Number} regX Optional.
   * @param {Number} regY Optional.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
    if (rotation%360) {
      var r = rotation*Matrix2D.DEG_TO_RAD;
      var cos = Math.cos(r);
      var sin = Math.sin(r);
    } else {
      cos = 1;
      sin = 0;
    }

    if (regX || regY) {
      // prepend the registration offset:
      this.tx -= regX; this.ty -= regY;
    }
    if (skewX || skewY) {
      // TODO: can this be combined into a single prepend operation?
      skewX *= Matrix2D.DEG_TO_RAD;
      skewY *= Matrix2D.DEG_TO_RAD;
      this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0);
      this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y);
    } else {
      this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y);
    }
    return this;
  };

  /**
   * Applies a clockwise rotation transformation to the matrix.
   * @method rotate
   * @param {Number} angle The angle to rotate by, in degrees. To use a value in radians, multiply it by `180/Math.PI`.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.rotate = function(angle) {
    angle = angle*Matrix2D.DEG_TO_RAD;
    var cos = Math.cos(angle);
    var sin = Math.sin(angle);

    var a1 = this.a;
    var b1 = this.b;

    this.a = a1*cos+this.c*sin;
    this.b = b1*cos+this.d*sin;
    this.c = -a1*sin+this.c*cos;
    this.d = -b1*sin+this.d*cos;
    return this;
  };

  /**
   * Applies a skew transformation to the matrix.
   * @method skew
   * @param {Number} skewX The amount to skew horizontally in degrees. To use a value in radians, multiply it by `180/Math.PI`.
   * @param {Number} skewY The amount to skew vertically in degrees.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
  */
  p.skew = function(skewX, skewY) {
    skewX = skewX*Matrix2D.DEG_TO_RAD;
    skewY = skewY*Matrix2D.DEG_TO_RAD;
    this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), 0, 0);
    return this;
  };

  /**
   * Applies a scale transformation to the matrix.
   * @method scale
   * @param {Number} x The amount to scale horizontally. E.G. a value of 2 will double the size in the X direction, and 0.5 will halve it.
   * @param {Number} y The amount to scale vertically.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.scale = function(x, y) {
    this.a *= x;
    this.b *= x;
    this.c *= y;
    this.d *= y;
    //this.tx *= x;
    //this.ty *= y;
    return this;
  };

  /**
   * Translates the matrix on the x and y axes.
   * @method translate
   * @param {Number} x
   * @param {Number} y
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.translate = function(x, y) {
    this.tx += this.a*x + this.c*y;
    this.ty += this.b*x + this.d*y;
    return this;
  };

  /**
   * Sets the properties of the matrix to those of an identity matrix (one that applies a null transformation).
   * @method identity
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.identity = function() {
    this.a = this.d = 1;
    this.b = this.c = this.tx = this.ty = 0;
    return this;
  };

  /**
   * Inverts the matrix, causing it to perform the opposite transformation.
   * @method invert
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
   **/
  p.invert = function() {
    var a1 = this.a;
    var b1 = this.b;
    var c1 = this.c;
    var d1 = this.d;
    var tx1 = this.tx;
    var n = a1*d1-b1*c1;

    this.a = d1/n;
    this.b = -b1/n;
    this.c = -c1/n;
    this.d = a1/n;
    this.tx = (c1*this.ty-d1*tx1)/n;
    this.ty = -(a1*this.ty-b1*tx1)/n;
    return this;
  };

  /**
   * Returns true if the matrix is an identity matrix.
   * @method isIdentity
   * @return {Boolean}
   **/
  p.isIdentity = function() {
    return this.tx === 0 && this.ty === 0 && this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1;
  };
  
  /**
   * Returns true if this matrix is equal to the specified matrix (all property values are equal).
   * @method equals
   * @param {Matrix2D} matrix The matrix to compare.
   * @return {Boolean}
   **/
  p.equals = function(matrix) {
    return this.tx === matrix.tx && this.ty === matrix.ty && this.a === matrix.a && this.b === matrix.b && this.c === matrix.c && this.d === matrix.d;
  };

  /**
   * Transforms a point according to this matrix.
   * @method transformPoint
   * @param {Number} x The x component of the point to transform.
   * @param {Number} y The y component of the point to transform.
   * @param {Point | Object} [pt] An object to copy the result into. If omitted a generic object with x/y properties will be returned.
   * @return {Point} This matrix. Useful for chaining method calls.
   **/
  p.transformPoint = function(x, y, pt) {
    pt = pt||{};
    pt.x = x*this.a+y*this.c+this.tx;
    pt.y = x*this.b+y*this.d+this.ty;
    return pt;
  };

  /**
   * Decomposes the matrix into transform properties (x, y, scaleX, scaleY, and rotation). Note that these values
   * may not match the transform properties you used to generate the matrix, though they will produce the same visual
   * results.
   * @method decompose
   * @param {Object} target The object to apply the transform properties to. If null, then a new object will be returned.
   * @return {Object} The target, or a new generic object with the transform properties applied.
  */
  p.decompose = function(target) {
    // TODO: it would be nice to be able to solve for whether the matrix can be decomposed into only scale/rotation even when scale is negative
    if (target == null) { target = {}; }
    target.x = this.tx;
    target.y = this.ty;
    target.scaleX = Math.sqrt(this.a * this.a + this.b * this.b);
    target.scaleY = Math.sqrt(this.c * this.c + this.d * this.d);

    var skewX = Math.atan2(-this.c, this.d);
    var skewY = Math.atan2(this.b, this.a);

    var delta = Math.abs(1-skewX/skewY);
    if (delta < 0.00001) { // effectively identical, can use rotation:
      target.rotation = skewY/Matrix2D.DEG_TO_RAD;
      if (this.a < 0 && this.d >= 0) {
        target.rotation += (target.rotation <= 0) ? 180 : -180;
      }
      target.skewX = target.skewY = 0;
    } else {
      target.skewX = skewX/Matrix2D.DEG_TO_RAD;
      target.skewY = skewY/Matrix2D.DEG_TO_RAD;
    }
    return target;
  };
  
  /**
   * Copies all properties from the specified matrix to this matrix.
   * @method copy
   * @param {Matrix2D} matrix The matrix to copy properties from.
   * @return {Matrix2D} This matrix. Useful for chaining method calls.
  */
  p.copy = function(matrix) {
    return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
  };

  /**
   * Returns a clone of the Matrix2D instance.
   * @method clone
   * @return {Matrix2D} a clone of the Matrix2D instance.
   **/
  p.clone = function() {
    return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty);
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]";
  };

  // this has to be populated after the class is defined:
  Matrix2D.identity = new Matrix2D();


  createjs.Matrix2D = Matrix2D;
}());

//##############################################################################
// DisplayProps.js
//##############################################################################

(function() {
  "use strict";

  /**
   * Used for calculating and encapsulating display related properties.
   * @class DisplayProps
   * @param {Number} [visible=true] Visible value.
   * @param {Number} [alpha=0] Alpha value.
   * @param {Number} [shadow=null] A Shadow instance or null.
   * @param {Number} [compositeOperation=null] A compositeOperation value or null.
   * @param {Number} [matrix] A transformation matrix. Defaults to a new identity matrix.
   * @constructor
   **/
  function DisplayProps(visible, alpha, shadow, compositeOperation, matrix) {
    this.setValues(visible, alpha, shadow, compositeOperation, matrix);
    
  // public properties:
    // assigned in the setValues method.
    /**
     * Property representing the alpha that will be applied to a display object.
     * @property alpha
     * @type Number
     **/
  
    /**
     * Property representing the shadow that will be applied to a display object.
     * @property shadow
     * @type Shadow
     **/
  
    /**
     * Property representing the compositeOperation that will be applied to a display object.
     * You can find a list of valid composite operations at:
     * <a href="https://developer.mozilla.org/en/Canvas_tutorial/Compositing">https://developer.mozilla.org/en/Canvas_tutorial/Compositing</a>
     * @property compositeOperation
     * @type String
     **/
    
    /**
     * Property representing the value for visible that will be applied to a display object.
     * @property visible
     * @type Boolean
     **/
    
    /**
     * The transformation matrix that will be applied to a display object.
     * @property matrix
     * @type Matrix2D
     **/
  }
  var p = DisplayProps.prototype;

// initialization:
  /**
   * Reinitializes the instance with the specified values.
   * @method setValues
   * @param {Number} [visible=true] Visible value.
   * @param {Number} [alpha=1] Alpha value.
   * @param {Number} [shadow=null] A Shadow instance or null.
   * @param {Number} [compositeOperation=null] A compositeOperation value or null.
   * @param {Number} [matrix] A transformation matrix. Defaults to an identity matrix.
   * @return {DisplayProps} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.setValues = function (visible, alpha, shadow, compositeOperation, matrix) {
    this.visible = visible == null ? true : !!visible;
    this.alpha = alpha == null ? 1 : alpha;
    this.shadow = shadow;
    this.compositeOperation = shadow;
    this.matrix = matrix || (this.matrix&&this.matrix.identity()) || new createjs.Matrix2D();
    return this;
  };

// public methods:
  /**
   * Appends the specified display properties. This is generally used to apply a child's properties its parent's.
   * @method append
   * @param {Boolean} visible desired visible value
   * @param {Number} alpha desired alpha value
   * @param {Shadow} shadow desired shadow value
   * @param {String} compositeOperation desired composite operation value
   * @param {Matrix2D} [matrix] a Matrix2D instance
   * @return {DisplayProps} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.append = function(visible, alpha, shadow, compositeOperation, matrix) {
    this.alpha *= alpha;
    this.shadow = shadow || this.shadow;
    this.compositeOperation = compositeOperation || this.compositeOperation;
    this.visible = this.visible && visible;
    matrix&&this.matrix.appendMatrix(matrix);
    return this;
  };
  
  /**
   * Prepends the specified display properties. This is generally used to apply a parent's properties to a child's.
   * For example, to get the combined display properties that would be applied to a child, you could use:
   * 
   *  var o = myDisplayObject;
   *  var props = new createjs.DisplayProps();
   *  do {
   *    // prepend each parent's props in turn:
   *    props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation, o.getMatrix());
   *  } while (o = o.parent);
   *  
   * @method prepend
   * @param {Boolean} visible desired visible value
   * @param {Number} alpha desired alpha value
   * @param {Shadow} shadow desired shadow value
   * @param {String} compositeOperation desired composite operation value
   * @param {Matrix2D} [matrix] a Matrix2D instance
   * @return {DisplayProps} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.prepend = function(visible, alpha, shadow, compositeOperation, matrix) {
    this.alpha *= alpha;
    this.shadow = this.shadow || shadow;
    this.compositeOperation = this.compositeOperation || compositeOperation;
    this.visible = this.visible && visible;
    matrix&&this.matrix.prependMatrix(matrix);
    return this;
  };
  
  /**
   * Resets this instance and its matrix to default values.
   * @method identity
   * @return {DisplayProps} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.identity = function() {
    this.visible = true;
    this.alpha = 1;
    this.shadow = this.compositeOperation = null;
    this.matrix.identity();
    return this;
  };
  
  /**
   * Returns a clone of the DisplayProps instance. Clones the associated matrix.
   * @method clone
   * @return {DisplayProps} a clone of the DisplayProps instance.
   **/
  p.clone = function() {
    return new DisplayProps(this.alpha, this.shadow, this.compositeOperation, this.visible, this.matrix.clone());
  };

// private methods:

  createjs.DisplayProps = DisplayProps;
})();

//##############################################################################
// Point.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Represents a point on a 2 dimensional x / y coordinate system.
   *
   * <h4>Example</h4>
   * 
   *      var point = new createjs.Point(0, 100);
   * 
   * @class Point
   * @param {Number} [x=0] X position.
   * @param {Number} [y=0] Y position.
   * @constructor
   **/
  function Point(x, y) {
    this.setValues(x, y);
    
    
  // public properties:
    // assigned in the setValues method.
    /**
     * X position.
     * @property x
     * @type Number
     **/
  
    /**
     * Y position.
     * @property y
     * @type Number
     **/
  }
  var p = Point.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.

  
// public methods:
  /** 
   * Sets the specified values on this instance.
   * @method setValues
   * @param {Number} [x=0] X position.
   * @param {Number} [y=0] Y position.
   * @return {Point} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.setValues = function(x, y) {
    this.x = x||0;
    this.y = y||0;
    return this;
  };
  
  /**
   * Copies all properties from the specified point to this point.
   * @method copy
   * @param {Point} point The point to copy properties from.
   * @return {Point} This point. Useful for chaining method calls.
   * @chainable
  */
  p.copy = function(point) {
    this.x = point.x;
    this.y = point.y;
    return this;
  };
  
  /**
   * Returns a clone of the Point instance.
   * @method clone
   * @return {Point} a clone of the Point instance.
   **/
  p.clone = function() {
    return new Point(this.x, this.y);
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Point (x="+this.x+" y="+this.y+")]";
  };
  
  
  createjs.Point = Point;
}());

//##############################################################################
// Rectangle.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Represents a rectangle as defined by the points (x, y) and (x+width, y+height).
   *
   * <h4>Example</h4>
   *
   *      var rect = new createjs.Rectangle(0, 0, 100, 100);
   *
   * @class Rectangle
   * @param {Number} [x=0] X position.
   * @param {Number} [y=0] Y position.
   * @param {Number} [width=0] The width of the Rectangle.
   * @param {Number} [height=0] The height of the Rectangle.
   * @constructor
   **/
  function Rectangle(x, y, width, height) {
    this.setValues(x, y, width, height);
    
    
  // public properties:
    // assigned in the setValues method.
    /**
     * X position.
     * @property x
     * @type Number
     **/
  
    /**
     * Y position.
     * @property y
     * @type Number
     **/
  
    /**
     * Width.
     * @property width
     * @type Number
     **/
  
    /**
     * Height.
     * @property height
     * @type Number
     **/
  }
  var p = Rectangle.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// public methods:
  /** 
   * Sets the specified values on this instance.
   * @method setValues
   * @param {Number} [x=0] X position.
   * @param {Number} [y=0] Y position.
   * @param {Number} [width=0] The width of the Rectangle.
   * @param {Number} [height=0] The height of the Rectangle.
   * @return {Rectangle} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.setValues = function(x, y, width, height) {
    // don't forget to update docs in the constructor if these change:
    this.x = x||0;
    this.y = y||0;
    this.width = width||0;
    this.height = height||0;
    return this;
  };
  
  /** 
   * Extends the rectangle's bounds to include the described point or rectangle.
   * @method extend
   * @param {Number} x X position of the point or rectangle.
   * @param {Number} y Y position of the point or rectangle.
   * @param {Number} [width=0] The width of the rectangle.
   * @param {Number} [height=0] The height of the rectangle.
   * @return {Rectangle} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.extend = function(x, y, width, height) {
    width = width||0;
    height = height||0;
    if (x+width > this.x+this.width) { this.width = x+width-this.x; }
    if (y+height > this.y+this.height) { this.height = y+height-this.y; }
    if (x < this.x) { this.width += this.x-x; this.x = x; }
    if (y < this.y) { this.height += this.y-y; this.y = y; }
    return this;
  };
  
  /** 
   * Adds the specified padding to the rectangle's bounds.
   * @method extend
   * @param {Number} [top=0]
   * @param {Number} [left=0]
   * @param {Number} [right=0]
   * @param {Number} [bottom=0]
   * @return {Rectangle} This instance. Useful for chaining method calls.
   * @chainable
  */
  p.pad = function(top, left, bottom, right) {
    this.x -= left;
    this.y -= top;
    this.width += left+right;
    this.height += top+bottom;
    return this;
  };
  
  /**
   * Copies all properties from the specified rectangle to this rectangle.
   * @method copy
   * @param {Rectangle} rectangle The rectangle to copy properties from.
   * @return {Rectangle} This rectangle. Useful for chaining method calls.
   * @chainable
  */
  p.copy = function(rectangle) {
    return this.setValues(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  };
  
  /** 
   * Returns true if this rectangle fully encloses the described point or rectangle.
   * @method contains
   * @param {Number} x X position of the point or rectangle.
   * @param {Number} y Y position of the point or rectangle.
   * @param {Number} [width=0] The width of the rectangle.
   * @param {Number} [height=0] The height of the rectangle.
   * @return {Boolean} True if the described point or rectangle is contained within this rectangle.
  */
  p.contains = function(x, y, width, height) {
    width = width||0;
    height = height||0;
    return (x >= this.x && x+width <= this.x+this.width && y >= this.y && y+height <= this.y+this.height);
  };
  
  /** 
   * Returns a new rectangle which contains this rectangle and the specified rectangle.
   * @method union
   * @param {Rectangle} rect The rectangle to calculate a union with.
   * @return {Rectangle} A new rectangle describing the union.
  */
  p.union = function(rect) {
    return this.clone().extend(rect.x, rect.y, rect.width, rect.height);
  };
  
  /** 
   * Returns a new rectangle which describes the intersection (overlap) of this rectangle and the specified rectangle,
   * or null if they do not intersect.
   * @method intersection
   * @param {Rectangle} rect The rectangle to calculate an intersection with.
   * @return {Rectangle} A new rectangle describing the intersection or null.
  */
  p.intersection = function(rect) {
    var x1 = rect.x, y1 = rect.y, x2 = x1+rect.width, y2 = y1+rect.height;
    if (this.x > x1) { x1 = this.x; }
    if (this.y > y1) { y1 = this.y; }
    if (this.x + this.width < x2) { x2 = this.x + this.width; }
    if (this.y + this.height < y2) { y2 = this.y + this.height; }
    return (x2 <= x1 || y2 <= y1) ? null : new Rectangle(x1, y1, x2-x1, y2-y1);
  };
  
  /** 
   * Returns true if the specified rectangle intersects (has any overlap) with this rectangle.
   * @method intersects
   * @param {Rectangle} rect The rectangle to compare.
   * @return {Boolean} True if the rectangles intersect.
  */
  p.intersects = function(rect) {
    return (rect.x <= this.x+this.width && this.x <= rect.x+rect.width && rect.y <= this.y+this.height && this.y <= rect.y + rect.height);
  };
  
  /** 
   * Returns true if the width or height are equal or less than 0.
   * @method isEmpty
   * @return {Boolean} True if the rectangle is empty.
  */
  p.isEmpty = function() {
    return this.width <= 0 || this.height <= 0;
  };
  
  /**
   * Returns a clone of the Rectangle instance.
   * @method clone
   * @return {Rectangle} a clone of the Rectangle instance.
   **/
  p.clone = function() {
    return new Rectangle(this.x, this.y, this.width, this.height);
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]";
  };
  
  
  createjs.Rectangle = Rectangle;
}());

//##############################################################################
// ButtonHelper.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * The ButtonHelper is a helper class to create interactive buttons from {{#crossLink "MovieClip"}}{{/crossLink}} or
   * {{#crossLink "Sprite"}}{{/crossLink}} instances. This class will intercept mouse events from an object, and
   * automatically call {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}},
   * to the respective animation labels, add a pointer cursor, and allows the user to define a hit state frame.
   *
   * The ButtonHelper instance does not need to be added to the stage, but a reference should be maintained to prevent
   * garbage collection.
   * 
   * Note that over states will not work unless you call {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *      var helper = new createjs.ButtonHelper(myInstance, "out", "over", "down", false, myInstance, "hit");
   *      myInstance.addEventListener("click", handleClick);
   *      function handleClick(event) {
   *          // Click Happened.
   *      }
   *
   * @class ButtonHelper
   * @param {Sprite|MovieClip} target The instance to manage.
   * @param {String} [outLabel="out"] The label or animation to go to when the user rolls out of the button.
   * @param {String} [overLabel="over"] The label or animation to go to when the user rolls over the button.
   * @param {String} [downLabel="down"] The label or animation to go to when the user presses the button.
   * @param {Boolean} [play=false] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing
   * states.
   * @param {DisplayObject} [hitArea] An optional item to use as the hit state for the button. If this is not defined,
   * then the button's visible states will be used instead. Note that the same instance as the "target" argument can be
   * used for the hitState.
   * @param {String} [hitLabel] The label or animation on the hitArea instance that defines the hitArea bounds. If this is
   * null, then the default state of the hitArea will be used. *
   * @constructor
   */
  function ButtonHelper(target, outLabel, overLabel, downLabel, play, hitArea, hitLabel) {
    if (!target.addEventListener) { return; }
  
  
  // public properties:
    /**
     * The target for this button helper.
     * @property target
     * @type MovieClip | Sprite
     * @readonly
     **/
    this.target = target;
  
    /**
     * The label name or frame number to display when the user mouses out of the target. Defaults to "over".
     * @property overLabel
     * @type String | Number
     **/
    this.overLabel = overLabel == null ? "over" : overLabel;
  
    /**
     * The label name or frame number to display when the user mouses over the target. Defaults to "out".
     * @property outLabel
     * @type String | Number
     **/
    this.outLabel = outLabel == null ? "out" : outLabel;
  
    /**
     * The label name or frame number to display when the user presses on the target. Defaults to "down".
     * @property downLabel
     * @type String | Number
     **/
    this.downLabel = downLabel == null ? "down" : downLabel;
  
    /**
     * If true, then ButtonHelper will call gotoAndPlay, if false, it will use gotoAndStop. Default is false.
     * @property play
     * @default false
     * @type Boolean
     **/
    this.play = play;
    
    
  //  private properties
    /**
     * @property _isPressed
     * @type Boolean
     * @protected
     **/
    this._isPressed = false;
  
    /**
     * @property _isOver
     * @type Boolean
     * @protected
     **/
    this._isOver = false;
  
    /**
     * @property _enabled
     * @type Boolean
     * @protected
     **/
    this._enabled = false;
    
  // setup:
    target.mouseChildren = false; // prevents issues when children are removed from the display list when state changes.
    this.enabled = true;
    this.handleEvent({});
    if (hitArea) {
      if (hitLabel) {
        hitArea.actionsEnabled = false;
        hitArea.gotoAndStop&&hitArea.gotoAndStop(hitLabel);
      }
      target.hitArea = hitArea;
    }
  }
  var p = ButtonHelper.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.

  
// getter / setters:
  /**
   * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead.
   * @method setEnabled
   * @param {Boolean} value
   * @deprecated
   **/
  p.setEnabled = function(value) { // TODO: deprecated.
    if (value == this._enabled) { return; }
    var o = this.target;
    this._enabled = value;
    if (value) {
      o.cursor = "pointer";
      o.addEventListener("rollover", this);
      o.addEventListener("rollout", this);
      o.addEventListener("mousedown", this);
      o.addEventListener("pressup", this);
      if (o._reset) { o.__reset = o._reset; o._reset = this._reset;}
    } else {
      o.cursor = null;
      o.removeEventListener("rollover", this);
      o.removeEventListener("rollout", this);
      o.removeEventListener("mousedown", this);
      o.removeEventListener("pressup", this);
      if (o.__reset) { o._reset = o.__reset; delete(o.__reset); }
    }
  };
  /**
   * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead.
   * @method getEnabled
   * @return {Boolean}
   * @deprecated
   **/
  p.getEnabled = function() {
    return this._enabled;
  };

  /**
   * Enables or disables the button functionality on the target.
   * @property enabled
   * @type {Boolean}
   **/
  try {
    Object.defineProperties(p, {
      enabled: { get: p.getEnabled, set: p.setEnabled }
    });
  } catch (e) {} // TODO: use Log


// public methods:
  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[ButtonHelper]";
  };


// private methods:
  /**
   * @method handleEvent
   * @param {Object} evt The mouse event to handle.
   * @protected
   **/
  p.handleEvent = function(evt) {
    var label, t = this.target, type = evt.type;
    if (type == "mousedown") {
      this._isPressed = true;
      label = this.downLabel;
    } else if (type == "pressup") {
      this._isPressed = false;
      label = this._isOver ? this.overLabel : this.outLabel;
    } else if (type == "rollover") {
      this._isOver = true;
      label = this._isPressed ? this.downLabel : this.overLabel;
    } else { // rollout and default
      this._isOver = false;
      label = this._isPressed ? this.overLabel : this.outLabel;
    }
    if (this.play) {
      t.gotoAndPlay&&t.gotoAndPlay(label);
    } else {
      t.gotoAndStop&&t.gotoAndStop(label);
    }
  };
  
  /**
   * Injected into target. Preserves the paused state through a reset.
   * @method _reset
   * @protected
   **/
  p._reset = function() {
    // TODO: explore better ways to handle this issue. This is hacky & disrupts object signatures.
    var p = this.paused;
    this.__reset();
    this.paused = p;
  };


  createjs.ButtonHelper = ButtonHelper;
}());

//##############################################################################
// Shadow.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * This class encapsulates the properties required to define a shadow to apply to a {{#crossLink "DisplayObject"}}{{/crossLink}}
   * via its <code>shadow</code> property.
   *
   * <h4>Example</h4>
   *
   *      myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10);
   *
   * @class Shadow
   * @constructor
   * @param {String} color The color of the shadow. This can be any valid CSS color value.
   * @param {Number} offsetX The x offset of the shadow in pixels.
   * @param {Number} offsetY The y offset of the shadow in pixels.
   * @param {Number} blur The size of the blurring effect.
   **/
  function Shadow(color, offsetX, offsetY, blur) {
    
    
  // public properties:
    /** 
     * The color of the shadow. This can be any valid CSS color value.
     * @property color
     * @type String
     * @default null
     */
    this.color = color||"black";
  
    /** The x offset of the shadow.
     * @property offsetX
     * @type Number
     * @default 0
     */
    this.offsetX = offsetX||0;
  
    /** The y offset of the shadow.
     * @property offsetY
     * @type Number
     * @default 0
     */
    this.offsetY = offsetY||0;
  
    /** The blur of the shadow.
     * @property blur
     * @type Number
     * @default 0
     */
    this.blur = blur||0;
  }
  var p = Shadow.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// static public properties:
  /**
   * An identity shadow object (all properties are set to 0).
   * @property identity
   * @type Shadow
   * @static
   * @final
   * @readonly
   **/
  Shadow.identity = new Shadow("transparent", 0, 0, 0);


// public methods:
  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Shadow]";
  };

  /**
   * Returns a clone of this Shadow instance.
   * @method clone
   * @return {Shadow} A clone of the current Shadow instance.
   **/
  p.clone = function() {
    return new Shadow(this.color, this.offsetX, this.offsetY, this.blur);
  };
  

  createjs.Shadow = Shadow;
}());

//##############################################################################
// SpriteSheet.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually
   * animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100
   * images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high).
   *
   * The data passed to the SpriteSheet constructor defines:<ol>
   *  <li> The source image or images to use.</li>
   *  <li> The positions of individual image frames.</li>
   *  <li> Sequences of frames that form named animations. Optional.</li>
   *  <li> The target playback framerate. Optional.</li>
   * </OL>
   *
   * <h3>SpriteSheet Format</h3>
   *
   * SpriteSheets are an object with two required properties (`images` and `frames`), and two optional properties
   * (`framerate` and `animations`). This makes them easy to define in javascript code, or in JSON.
   *
   * <h4>images</h4>
   * An array of source images. Images can be either an HTMLImage
   * instance, or a uri to an image. The former is recommended to control preloading.
   *
   *  images: [image1, "path/to/image2.png"],
   *
   * <h4>frames</h4>
   * Defines the individual frames. There are two supported formats for frame data:<OL>
   * <LI> when all of the frames are the same size (in a grid), use an object with `width`, `height`, `regX`, `regY`, and `count` properties.
   * `width` & `height` are required and specify the dimensions of the frames.
   * `regX` & `regY` indicate the registration point or "origin" of the frames.
   * `spacing` indicate the spacing between frames.
   * `margin` specify the margin around the image(s).
   * `count` allows you to specify the total number of frames in the spritesheet; if omitted, this will be calculated
   * based on the dimensions of the source images and the frames. Frames will be assigned indexes based on their position
   * in the source images (left to right, top to bottom).
   *
   *  frames: {width:64, height:64, count:20, regX: 32, regY:64, spacing:0, margin:0}
   *
   * <LI> if the frames are of different sizes, use an array of frame definitions. Each definition is itself an array
   * with 4 required and 3 optional entries, in the order: `x`, `y`, `width`, `height`, `imageIndex`, `regX`, `regY`. The first
   * four entries are required and define the frame rectangle. The fifth specifies the index of the source image (defaults to 0). The
   * last two specify the registration point of the frame.
   *
   *  frames: [
   *    // x, y, width, height, imageIndex*, regX*, regY*
   *    [64, 0, 96, 64],
   *    [0, 0, 64, 64, 1, 32, 32]
   *    // etc.
   *  ]
   *
   * </OL>
   *
   * <h4>animations</h4>
   * Optional. An object defining sequences of frames to play as named animations. Each property corresponds to an
   * animation of the same name. Each animation must specify the frames to play, and may
   * also include a relative playback `speed` (ex. 2 would playback at double speed, 0.5 at half), and
   * the name of the `next` animation to sequence to after it completes.
   *
   * There are three formats supported for defining the frames in an animation, which can be mixed and matched as appropriate:<OL>
   * <LI> for a single frame animation, you can simply specify the frame index
   *
   *  animations: {
   *    sit: 7
   *  }
   *
   * <LI> for an animation of consecutive frames, you can use an array with two required, and two optional entries
   * in the order: `start`, `end`, `next`, and `speed`. This will play the frames from start to end inclusive.
   *
   *  animations: {
   *    // start, end, next*, speed*
   *    run: [0, 8],
   *    jump: [9, 12, "run", 2]
   *  }
   *
   * <LI> for non-consecutive frames, you can use an object with a `frames` property defining an array of frame indexes to
   * play in order. The object can also specify `next` and `speed` properties.
   *
   *  animations: {
   *    walk: {
   *      frames: [1,2,3,3,2,1]
   *    },
   *    shoot: {
   *      frames: [1,4,5,6],
   *      next: "walk",
   *      speed: 0.5
   *    }
   *  }
   *
   * </OL>
   * <strong>Note:</strong> the `speed` property was added in EaselJS 0.7.0. Earlier versions had a `frequency`
   * property instead, which was the inverse of `speed`. For example, a value of "4" would be 1/4 normal speed in earlier
   * versions, but is 4x normal speed in 0.7.0+.
   *
   * <h4>framerate</h4>
   * Optional. Indicates the default framerate to play this spritesheet at in frames per second.
   * See {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} for more information.
   *
   *  framerate: 20
   *
   * <h4>Example</h4>
   * To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with three
   * animations: "stand" showing the first frame, "run" looping frame 1-5 inclusive, and "jump" playing  frame 6-8 and sequencing back to run.
   *
   *  var data = {
   *    images: ["sprites.jpg"],
   *    frames: {width:50, height:50},
   *    animations: {
   *      stand:0,
   *      run:[1,5],
   *      jump:[6,8,"run"]
   *    }
   *  };
   *  var spriteSheet = new createjs.SpriteSheet(data);
   *  var animation = new createjs.Sprite(spriteSheet, "run");
   *
   *
   * <strong>Warning:</strong> Images loaded cross-origin will throw cross-origin security errors when interacted with
   * using a mouse, using methods such as `getObjectUnderPoint`, using filters, or caching. You can get around this by
   * setting `crossOrigin` flags on your images before passing them to EaselJS, eg: `img.crossOrigin="Anonymous";`
   *
   * @class SpriteSheet
   * @constructor
   * @param {Object} data An object describing the SpriteSheet data.
   * @extends EventDispatcher
   **/
  function SpriteSheet(data) {
    this.EventDispatcher_constructor();


    // public properties:
    /**
     * Indicates whether all images are finished loading.
     * @property complete
     * @type Boolean
     * @readonly
     **/
    this.complete = true;

    /**
     * Specifies the framerate to use by default for Sprite instances using the SpriteSheet. See
     * Sprite.framerate for more information.
     * @property framerate
     * @type Number
     **/
    this.framerate = 0;


    // private properties:
    /**
     * @property _animations
     * @protected
     * @type Array
     **/
    this._animations = null;

    /**
     * @property _frames
     * @protected
     * @type Array
     **/
    this._frames = null;

    /**
     * @property _images
     * @protected
     * @type Array
     **/
    this._images = null;

    /**
     * @property _data
     * @protected
     * @type Object
     **/
    this._data = null;

    /**
     * @property _loadCount
     * @protected
     * @type Number
     **/
    this._loadCount = 0;

    // only used for simple frame defs:
    /**
     * @property _frameHeight
     * @protected
     * @type Number
     **/
    this._frameHeight = 0;

    /**
     * @property _frameWidth
     * @protected
     * @type Number
     **/
    this._frameWidth = 0;

    /**
     * @property _numFrames
     * @protected
     * @type Number
     **/
    this._numFrames = 0;

    /**
     * @property _regX
     * @protected
     * @type Number
     **/
    this._regX = 0;

    /**
     * @property _regY
     * @protected
     * @type Number
     **/
    this._regY = 0;

    /**
     * @property _spacing
     * @protected
     * @type Number
     **/
    this._spacing = 0;

    /**
     * @property _margin
     * @protected
     * @type Number
     **/
    this._margin = 0;

    // setup:
    this._parseData(data);
  }
  var p = createjs.extend(SpriteSheet, createjs.EventDispatcher);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// events:
  /**
   * Dispatched when all images are loaded.  Note that this only fires if the images
   * were not fully loaded when the sprite sheet was initialized. You should check the complete property
   * to prior to adding a listener. Ex.
   *
   *  var sheet = new SpriteSheet(data);
   *  if (!sheet.complete) {
   *    // not preloaded, listen for the complete event:
   *    sheet.addEventListener("complete", handler);
   *  }
   *
   * @event complete
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @since 0.6.0
   */

  /**
   * Dispatched when getFrame is called with a valid frame index. This is primarily intended for use by {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}}
   * when doing on-demand rendering.
   * @event getframe
   * @param {Number} index The frame index.
   * @param {Object} frame The frame object that getFrame will return.
   */


// getter / setters:
  /**
   * Use the {{#crossLink "SpriteSheet/animations:property"}}{{/crossLink}} property instead.
   * @method getAnimations
   * @return {Array}
   * @deprecated
   **/
  p.getAnimations = function() {
    return this._animations.slice();
  };

  /**
   * Returns an array of all available animation names available on this sprite sheet as strings.
   * @property animations
   * @type {Array}
   * @readonly
   **/
  try {
    Object.defineProperties(p, {
      animations: { get: p.getAnimations }
    });
  } catch (e) {}


// public methods:
  /**
   * Returns the total number of frames in the specified animation, or in the whole sprite
   * sheet if the animation param is omitted. Returns 0 if the spritesheet relies on calculated frame counts, and
   * the images have not been fully loaded.
   * @method getNumFrames
   * @param {String} animation The name of the animation to get a frame count for.
   * @return {Number} The number of frames in the animation, or in the entire sprite sheet if the animation param is omitted.
   */
  p.getNumFrames = function(animation) {
    if (animation == null) {
      return this._frames ? this._frames.length : this._numFrames || 0;
    } else {
      var data = this._data[animation];
      if (data == null) { return 0; }
      else { return data.frames.length; }
    }
  };

  /**
   * Returns an object defining the specified animation. The returned object contains:<UL>
   *  <LI>frames: an array of the frame ids in the animation</LI>
   *  <LI>speed: the playback speed for this animation</LI>
   *  <LI>name: the name of the animation</LI>
   *  <LI>next: the default animation to play next. If the animation loops, the name and next property will be the
   *  same.</LI>
   * </UL>
   * @method getAnimation
   * @param {String} name The name of the animation to get.
   * @return {Object} a generic object with frames, speed, name, and next properties.
   **/
  p.getAnimation = function(name) {
    return this._data[name];
  };

  /**
   * Returns an object specifying the image and source rect of the specified frame. The returned object has:<UL>
   *  <LI>an image property holding a reference to the image object in which the frame is found</LI>
   *  <LI>a rect property containing a Rectangle instance which defines the boundaries for the frame within that
   *  image.</LI>
   *  <LI> A regX and regY property corresponding to the regX/Y values for the frame.
   * </UL>
   * @method getFrame
   * @param {Number} frameIndex The index of the frame.
   * @return {Object} a generic object with image and rect properties. Returns null if the frame does not exist.
   **/
  p.getFrame = function(frameIndex) {
    var frame;
    if (this._frames && (frame=this._frames[frameIndex])) { return frame; }
    return null;
  };

  /**
   * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the specified frame relative
   * to the origin. For example, a 90 x 70 frame with a regX of 50 and a regY of 40 would return:
   *
   *  [x=-50, y=-40, width=90, height=70]
   *
   * @method getFrameBounds
   * @param {Number} frameIndex The index of the frame.
   * @param {Rectangle} [rectangle] A Rectangle instance to copy the values into. By default a new instance is created.
   * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully loaded.
   **/
  p.getFrameBounds = function(frameIndex, rectangle) {
    var frame = this.getFrame(frameIndex);
    return frame ? (rectangle||new createjs.Rectangle()).setValues(-frame.regX, -frame.regY, frame.rect.width, frame.rect.height) : null;
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[SpriteSheet]";
  };

  /**
   * SpriteSheet cannot be cloned. A SpriteSheet can be shared by multiple Sprite instances without cloning it.
   * @method clone
   **/
  p.clone = function() {
    throw("SpriteSheet cannot be cloned.")
  };

// private methods:
  /**
   * @method _parseData
   * @param {Object} data An object describing the SpriteSheet data.
   * @protected
   **/
  p._parseData = function(data) {
    var i,l,o,a;
    if (data == null) { return; }

    this.framerate = data.framerate||0;

    // parse images:
    if (data.images && (l=data.images.length) > 0) {
      a = this._images = [];
      for (i=0; i<l; i++) {
        var img = data.images[i];
        if (typeof img == "string") {
          var src = img;
          img = document.createElement("img");
          img.src = src;
        }
        a.push(img);
        if (!img.getContext && !img.naturalWidth) {
          this._loadCount++;
          this.complete = false;
          (function(o) { img.onload = function() { o._handleImageLoad(); } })(this);
        }
      }
    }

    // parse frames:
    if (data.frames == null) { // nothing
    } else if (data.frames instanceof Array) {
      this._frames = [];
      a = data.frames;
      for (i=0,l=a.length;i<l;i++) {
        var arr = a[i];
        this._frames.push({image:this._images[arr[4]?arr[4]:0], rect:new createjs.Rectangle(arr[0],arr[1],arr[2],arr[3]), regX:arr[5]||0, regY:arr[6]||0 });
      }
    } else {
      o = data.frames;
      this._frameWidth = o.width;
      this._frameHeight = o.height;
      this._regX = o.regX||0;
      this._regY = o.regY||0;
      this._spacing = o.spacing||0;
      this._margin = o.margin||0;
      this._numFrames = o.count;
      if (this._loadCount == 0) { this._calculateFrames(); }
    }

    // parse animations:
    this._animations = [];
    if ((o=data.animations) != null) {
      this._data = {};
      var name;
      for (name in o) {
        var anim = {name:name};
        var obj = o[name];
        if (typeof obj == "number") { // single frame
          a = anim.frames = [obj];
        } else if (obj instanceof Array) { // simple
          if (obj.length == 1) { anim.frames = [obj[0]]; }
          else {
            anim.speed = obj[3];
            anim.next = obj[2];
            a = anim.frames = [];
            for (i=obj[0];i<=obj[1];i++) {
              a.push(i);
            }
          }
        } else { // complex
          anim.speed = obj.speed;
          anim.next = obj.next;
          var frames = obj.frames;
          a = anim.frames = (typeof frames == "number") ? [frames] : frames.slice(0);
        }
        if (anim.next === true || anim.next === undefined) { anim.next = name; } // loop
        if (anim.next === false || (a.length < 2 && anim.next == name)) { anim.next = null; } // stop
        if (!anim.speed) { anim.speed = 1; }
        this._animations.push(name);
        this._data[name] = anim;
      }
    }
  };

  /**
   * @method _handleImageLoad
   * @protected
   **/
  p._handleImageLoad = function() {
    if (--this._loadCount == 0) {
      this._calculateFrames();
      this.complete = true;
      this.dispatchEvent("complete");
    }
  };

  /**
   * @method _calculateFrames
   * @protected
   **/
  p._calculateFrames = function() {
    if (this._frames || this._frameWidth == 0) { return; }

    this._frames = [];

    var maxFrames = this._numFrames || 100000; // if we go over this, something is wrong.
    var frameCount = 0, frameWidth = this._frameWidth, frameHeight = this._frameHeight;
    var spacing = this._spacing, margin = this._margin;
    
    imgLoop:
    for (var i=0, imgs=this._images; i<imgs.length; i++) {
      var img = imgs[i], imgW = img.width, imgH = img.height;

      var y = margin;
      while (y <= imgH-margin-frameHeight) {
        var x = margin;
        while (x <= imgW-margin-frameWidth) {
          if (frameCount >= maxFrames) { break imgLoop; }
          frameCount++;
          this._frames.push({
              image: img,
              rect: new createjs.Rectangle(x, y, frameWidth, frameHeight),
              regX: this._regX,
              regY: this._regY
            });
          x += frameWidth+spacing;
        }
        y += frameHeight+spacing;
      }
    }
    this._numFrames = frameCount;
  };


  createjs.SpriteSheet = createjs.promote(SpriteSheet, "EventDispatcher");
}());

//##############################################################################
// Graphics.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a
   * specified context. Note that you can use Graphics without any dependency on the EaselJS framework by calling {{#crossLink "Graphics/draw"}}{{/crossLink}}
   * directly, or it can be used with the {{#crossLink "Shape"}}{{/crossLink}} object to draw vector graphics within the
   * context of an EaselJS display list.
   *
   * There are two approaches to working with Graphics object: calling methods on a Graphics instance (the "Graphics API"), or
   * instantiating Graphics command objects and adding them to the graphics queue via {{#crossLink "Graphics/append"}}{{/crossLink}}.
   * The former abstracts the latter, simplifying beginning and ending paths, fills, and strokes.
   *
   *      var g = new createjs.Graphics();
   *      g.setStrokeStyle(1);
   *      g.beginStroke("#000000");
   *      g.beginFill("red");
   *      g.drawCircle(0,0,30);
   *
   * All drawing methods in Graphics return the Graphics instance, so they can be chained together. For example,
   * the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill:
   *
   *      myGraphics.beginStroke("red").beginFill("blue").drawRect(20, 20, 100, 50);
   *
   * Each graphics API call generates a command object (see below). The last command to be created can be accessed via
   * {{#crossLink "Graphics/command:property"}}{{/crossLink}}:
   *
   *      var fillCommand = myGraphics.beginFill("red").command;
   *      // ... later, update the fill style/color:
   *      fillCommand.style = "blue";
   *      // or change it to a bitmap fill:
   *      fillCommand.bitmap(myImage);
   *
   * For more direct control of rendering, you can instantiate and append command objects to the graphics queue directly. In this case, you
   * need to manage path creation manually, and ensure that fill/stroke is applied to a defined path:
   *
   *      // start a new path. Graphics.beginCmd is a reusable BeginPath instance:
   *      myGraphics.append(createjs.Graphics.beginCmd);
   *      // we need to define the path before applying the fill:
   *      var circle = new createjs.Graphics.Circle(0,0,30);
   *      myGraphics.append(circle);
   *      // fill the path we just defined:
   *      var fill = new createjs.Graphics.Fill("red");
   *      myGraphics.append(fill);
   *
   * These approaches can be used together, for example to insert a custom command:
   *
   *      myGraphics.beginFill("red");
   *      var customCommand = new CustomSpiralCommand(etc);
   *      myGraphics.append(customCommand);
   *      myGraphics.beginFill("blue");
   *      myGraphics.drawCircle(0, 0, 30);
   *
   * See {{#crossLink "Graphics/append"}}{{/crossLink}} for more info on creating custom commands.
   *
   * <h4>Tiny API</h4>
   * The Graphics class also includes a "tiny API", which is one or two-letter methods that are shortcuts for all of the
   * Graphics methods. These methods are great for creating compact instructions, and is used by the Toolkit for CreateJS
   * to generate readable code. All tiny methods are marked as protected, so you can view them by enabling protected
   * descriptions in the docs.
   *
   * <table>
   *     <tr><td><b>Tiny</b></td><td><b>Method</b></td><td><b>Tiny</b></td><td><b>Method</b></td></tr>
   *     <tr><td>mt</td><td>{{#crossLink "Graphics/moveTo"}}{{/crossLink}} </td>
   *     <td>lt</td> <td>{{#crossLink "Graphics/lineTo"}}{{/crossLink}}</td></tr>
   *     <tr><td>a/at</td><td>{{#crossLink "Graphics/arc"}}{{/crossLink}} / {{#crossLink "Graphics/arcTo"}}{{/crossLink}} </td>
   *     <td>bt</td><td>{{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} </td></tr>
   *     <tr><td>qt</td><td>{{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} (also curveTo)</td>
   *     <td>r</td><td>{{#crossLink "Graphics/rect"}}{{/crossLink}} </td></tr>
   *     <tr><td>cp</td><td>{{#crossLink "Graphics/closePath"}}{{/crossLink}} </td>
   *     <td>c</td><td>{{#crossLink "Graphics/clear"}}{{/crossLink}} </td></tr>
   *     <tr><td>f</td><td>{{#crossLink "Graphics/beginFill"}}{{/crossLink}} </td>
   *     <td>lf</td><td>{{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} </td></tr>
   *     <tr><td>rf</td><td>{{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} </td>
   *     <td>bf</td><td>{{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} </td></tr>
   *     <tr><td>ef</td><td>{{#crossLink "Graphics/endFill"}}{{/crossLink}} </td>
   *     <td>ss / sd</td><td>{{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} / {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} </td></tr>
   *     <tr><td>s</td><td>{{#crossLink "Graphics/beginStroke"}}{{/crossLink}} </td>
   *     <td>ls</td><td>{{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} </td></tr>
   *     <tr><td>rs</td><td>{{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} </td>
   *     <td>bs</td><td>{{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} </td></tr>
   *     <tr><td>es</td><td>{{#crossLink "Graphics/endStroke"}}{{/crossLink}} </td>
   *     <td>dr</td><td>{{#crossLink "Graphics/drawRect"}}{{/crossLink}} </td></tr>
   *     <tr><td>rr</td><td>{{#crossLink "Graphics/drawRoundRect"}}{{/crossLink}} </td>
   *     <td>rc</td><td>{{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} </td></tr>
   *     <tr><td>dc</td><td>{{#crossLink "Graphics/drawCircle"}}{{/crossLink}} </td>
   *     <td>de</td><td>{{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} </td></tr>
   *     <tr><td>dp</td><td>{{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} </td>
   *     <td>p</td><td>{{#crossLink "Graphics/decodePath"}}{{/crossLink}} </td></tr>
   * </table>
   *
   * Here is the above example, using the tiny API instead.
   *
   *      myGraphics.s("red").f("blue").r(20, 20, 100, 50);
   *
   * @class Graphics
   * @constructor
   **/
  function Graphics() {


  // public properties
    /**
     * Holds a reference to the last command that was created or appended. For example, you could retain a reference
     * to a Fill command in order to dynamically update the color later by using:
     *    myFill = myGraphics.beginFill("red").command;
     *    // update color later:
     *    myFill.style = "yellow";
     * @property command
     * @type Object
     **/
    this.command = null;


  // private properties
    /**
     * @property _stroke
     * @protected
     * @type {Stroke}
     **/
    this._stroke = null;

    /**
     * @property _strokeStyle
     * @protected
     * @type {StrokeStyle}
     **/
    this._strokeStyle = null;
    
    /**
     * @property _oldStrokeStyle
     * @protected
     * @type {StrokeStyle}
     **/
    this._oldStrokeStyle = null;
    
    /**
     * @property _strokeDash
     * @protected
     * @type {StrokeDash}
     **/
    this._strokeDash = null;
    
    /**
     * @property _oldStrokeDash
     * @protected
     * @type {StrokeDash}
     **/
    this._oldStrokeDash = null;

    /**
     * @property _strokeIgnoreScale
     * @protected
     * @type Boolean
     **/
    this._strokeIgnoreScale = false;

    /**
     * @property _fill
     * @protected
     * @type {Fill}
     **/
    this._fill = null;

    /**
     * @property _instructions
     * @protected
     * @type {Array}
     **/
    this._instructions = [];

    /**
     * Indicates the last instruction index that was committed.
     * @property _commitIndex
     * @protected
     * @type {Number}
     **/
    this._commitIndex = 0;

    /**
     * Uncommitted instructions.
     * @property _activeInstructions
     * @protected
     * @type {Array}
     **/
    this._activeInstructions = [];

    /**
     * This indicates that there have been changes to the activeInstruction list since the last updateInstructions call.
     * @property _dirty
     * @protected
     * @type {Boolean}
     * @default false
     **/
    this._dirty = false;

    /**
     * Index to draw from if a store operation has happened.
     * @property _storeIndex
     * @protected
     * @type {Number}
     * @default 0
     **/
    this._storeIndex = 0;

  // setup:
    this.clear();
  }
  var p = Graphics.prototype;
  var G = Graphics; // shortcut

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// static public methods:
  /**
   * Returns a CSS compatible color string based on the specified RGB numeric color values in the format
   * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". For example,
   *
   *      createjs.Graphics.getRGB(50, 100, 150, 0.5);
   *      // Returns "rgba(50,100,150,0.5)"
   *
   * It also supports passing a single hex color value as the first param, and an optional alpha value as the second
   * param. For example,
   *
   *      createjs.Graphics.getRGB(0xFF00FF, 0.2);
   *      // Returns "rgba(255,0,255,0.2)"
   *
   * @method getRGB
   * @static
   * @param {Number} r The red component for the color, between 0 and 0xFF (255).
   * @param {Number} g The green component for the color, between 0 and 0xFF (255).
   * @param {Number} b The blue component for the color, between 0 and 0xFF (255).
   * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque.
   * @return {String} A CSS compatible color string based on the specified RGB numeric color values in the format
   * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)".
   **/
  Graphics.getRGB = function(r, g, b, alpha) {
    if (r != null && b == null) {
      alpha = g;
      b = r&0xFF;
      g = r>>8&0xFF;
      r = r>>16&0xFF;
    }
    if (alpha == null) {
      return "rgb("+r+","+g+","+b+")";
    } else {
      return "rgba("+r+","+g+","+b+","+alpha+")";
    }
  };

  /**
   * Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)",
   * or if alpha is null then in the format "hsl(360,100,100)".
   *
   *      createjs.Graphics.getHSL(150, 100, 70);
   *      // Returns "hsl(150,100,70)"
   *
   * @method getHSL
   * @static
   * @param {Number} hue The hue component for the color, between 0 and 360.
   * @param {Number} saturation The saturation component for the color, between 0 and 100.
   * @param {Number} lightness The lightness component for the color, between 0 and 100.
   * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque.
   * @return {String} A CSS compatible color string based on the specified HSL numeric color values in the format
   * "hsla(360,100,100,1.0)", or if alpha is null then in the format "hsl(360,100,100)".
   **/
  Graphics.getHSL = function(hue, saturation, lightness, alpha) {
    if (alpha == null) {
      return "hsl("+(hue%360)+","+saturation+"%,"+lightness+"%)";
    } else {
      return "hsla("+(hue%360)+","+saturation+"%,"+lightness+"%,"+alpha+")";
    }
  };


// static properties:
  /**
   * A reusable instance of {{#crossLink "Graphics/BeginPath"}}{{/crossLink}} to avoid
   * unnecessary instantiation.
   * @property beginCmd
   * @type {Graphics.BeginPath}
   * @static
   **/
   // defined at the bottom of this file.

  /**
   * Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}.
   * @property BASE_64
   * @static
   * @final
   * @readonly
   * @type {Object}
   **/
  Graphics.BASE_64 = {"A":0,"B":1,"C":2,"D":3,"E":4,"F":5,"G":6,"H":7,"I":8,"J":9,"K":10,"L":11,"M":12,"N":13,"O":14,"P":15,"Q":16,"R":17,"S":18,"T":19,"U":20,"V":21,"W":22,"X":23,"Y":24,"Z":25,"a":26,"b":27,"c":28,"d":29,"e":30,"f":31,"g":32,"h":33,"i":34,"j":35,"k":36,"l":37,"m":38,"n":39,"o":40,"p":41,"q":42,"r":43,"s":44,"t":45,"u":46,"v":47,"w":48,"x":49,"y":50,"z":51,"0":52,"1":53,"2":54,"3":55,"4":56,"5":57,"6":58,"7":59,"8":60,"9":61,"+":62,"/":63};

  /**
   * Maps numeric values for the caps parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to
   * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to
   * "butt", 1 to "round", and 2 to "square".
   * For example, to set the line caps to "square":
   *
   *      myGraphics.ss(16, 2);
   *
   * @property STROKE_CAPS_MAP
   * @static
   * @final
   * @readonly
   * @type {Array}
   **/
  Graphics.STROKE_CAPS_MAP = ["butt", "round", "square"];

  /**
   * Maps numeric values for the joints parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to
   * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to
   * "miter", 1 to "round", and 2 to "bevel".
   * For example, to set the line joints to "bevel":
   *
   *      myGraphics.ss(16, 0, 2);
   *
   * @property STROKE_JOINTS_MAP
   * @static
   * @final
   * @readonly
   * @type {Array}
   **/
  Graphics.STROKE_JOINTS_MAP = ["miter", "round", "bevel"];

  /**
   * @property _ctx
   * @static
   * @protected
   * @type {CanvasRenderingContext2D}
   **/
  var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
  if (canvas.getContext) {
    Graphics._ctx = canvas.getContext("2d");
    canvas.width = canvas.height = 1;
  }


// getter / setters:
  /**
   * Use the {{#crossLink "Graphics/instructions:property"}}{{/crossLink}} property instead.
   * @method getInstructions
   * @return {Array}
   * @deprecated
   **/
  p.getInstructions = function() {
    this._updateInstructions();
    return this._instructions;
  };

  /**
   * Returns the graphics instructions array. Each entry is a graphics command object (ex. Graphics.Fill, Graphics.Rect)
   * Modifying the returned array directly is not recommended, and is likely to result in unexpected behaviour.
   *
   * This property is mainly intended for introspection of the instructions (ex. for graphics export).
   * @property instructions
   * @type {Array}
   * @readonly
   **/
  try {
    Object.defineProperties(p, {
      instructions: { get: p.getInstructions }
    });
  } catch (e) {}


// public methods:
  /**
   * Returns true if this Graphics instance has no drawing commands.
   * @method isEmpty
   * @return {Boolean} Returns true if this Graphics instance has no drawing commands.
   **/
  p.isEmpty = function() {
    return !(this._instructions.length || this._activeInstructions.length);
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Object} data Optional data that is passed to graphics command exec methods. When called from a Shape instance, the shape passes itself as the data parameter. This can be used by custom graphic commands to insert contextual data.
   **/
  p.draw = function(ctx, data) {
    this._updateInstructions();
    var instr = this._instructions;
    for (var i=this._storeIndex, l=instr.length; i<l; i++) {
      instr[i].exec(ctx, data);
    }
  };

  /**
   * Draws only the path described for this Graphics instance, skipping any non-path instructions, including fill and
   * stroke descriptions. Used for <code>DisplayObject.mask</code> to draw the clipping path, for example.
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method drawAsPath
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   **/
  p.drawAsPath = function(ctx) {
    this._updateInstructions();
    var instr, instrs = this._instructions;
    for (var i=this._storeIndex, l=instrs.length; i<l; i++) {
      // the first command is always a beginPath command.
      if ((instr = instrs[i]).path !== false) { instr.exec(ctx); }
    }
  };


// public methods that map directly to context 2D calls:
  /**
   * Moves the drawing point to the specified position. A tiny API method "mt" also exists.
   * @method moveTo
   * @param {Number} x The x coordinate the drawing point should move to.
   * @param {Number} y The y coordinate the drawing point should move to.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls).
   * @chainable
   **/
  p.moveTo = function(x, y) {
    return this.append(new G.MoveTo(x,y), true);
  };

  /**
   * Draws a line from the current drawing point to the specified position, which become the new current drawing
   * point. A tiny API method "lt" also exists.
   *
   * For detailed information, read the
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#complex-shapes-(paths)">
   * whatwg spec</a>.
   * @method lineTo
   * @param {Number} x The x coordinate the drawing point should draw to.
   * @param {Number} y The y coordinate the drawing point should draw to.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.lineTo = function(x, y) {
    return this.append(new G.LineTo(x,y));
  };

  /**
   * Draws an arc with the specified control points and radius.  For detailed information, read the
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arcto">
   * whatwg spec</a>. A tiny API method "at" also exists.
   * @method arcTo
   * @param {Number} x1
   * @param {Number} y1
   * @param {Number} x2
   * @param {Number} y2
   * @param {Number} radius
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.arcTo = function(x1, y1, x2, y2, radius) {
    return this.append(new G.ArcTo(x1, y1, x2, y2, radius));
  };

  /**
   * Draws an arc defined by the radius, startAngle and endAngle arguments, centered at the position (x, y). For
   * example, to draw a full circle with a radius of 20 centered at (100, 100):
   *
   *      arc(100, 100, 20, 0, Math.PI*2);
   *
   * For detailed information, read the
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc">whatwg spec</a>.
   * A tiny API method "a" also exists.
   * @method arc
   * @param {Number} x
   * @param {Number} y
   * @param {Number} radius
   * @param {Number} startAngle Measured in radians.
   * @param {Number} endAngle Measured in radians.
   * @param {Boolean} anticlockwise
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) {
    return this.append(new G.Arc(x, y, radius, startAngle, endAngle, anticlockwise));
  };

  /**
   * Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed
   * information, read the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-quadraticcurveto">
   * whatwg spec</a>. A tiny API method "qt" also exists.
   * @method quadraticCurveTo
   * @param {Number} cpx
   * @param {Number} cpy
   * @param {Number} x
   * @param {Number} y
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.quadraticCurveTo = function(cpx, cpy, x, y) {
    return this.append(new G.QuadraticCurveTo(cpx, cpy, x, y));
  };

  /**
   * Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x,
   * cp2y). For detailed information, read the
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-beziercurveto">
   * whatwg spec</a>. A tiny API method "bt" also exists.
   * @method bezierCurveTo
   * @param {Number} cp1x
   * @param {Number} cp1y
   * @param {Number} cp2x
   * @param {Number} cp2y
   * @param {Number} x
   * @param {Number} y
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
    return this.append(new G.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y));
  };

  /**
   * Draws a rectangle at (x, y) with the specified width and height using the current fill and/or stroke.
   * For detailed information, read the
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-rect">
   * whatwg spec</a>. A tiny API method "r" also exists.
   * @method rect
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w Width of the rectangle
   * @param {Number} h Height of the rectangle
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.rect = function(x, y, w, h) {
    return this.append(new G.Rect(x, y, w, h));
  };

  /**
   * Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified
   * since the fill or stroke was last set. A tiny API method "cp" also exists.
   * @method closePath
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.closePath = function() {
    return this._activeInstructions.length ? this.append(new G.ClosePath()) : this;
  };


// public methods that roughly map to Flash graphics APIs:
  /**
   * Clears all drawing instructions, effectively resetting this Graphics instance. Any line and fill styles will need
   * to be redefined to draw shapes following a clear call. A tiny API method "c" also exists.
   * @method clear
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.clear = function() {
    this._instructions.length = this._activeInstructions.length = this._commitIndex = 0;
    this._strokeStyle = this._oldStrokeStyle = this._stroke = this._fill = this._strokeDash = this._oldStrokeDash = null;
    this._dirty = this._strokeIgnoreScale = false;
    return this;
  };

  /**
   * Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists.
   * @method beginFill
   * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to
   * null will result in no fill.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginFill = function(color) {
    return this._setFill(color ? new G.Fill(color) : null);
  };

  /**
   * Begins a linear gradient fill defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For
   * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a
   * square to display it:
   *
   *      myGraphics.beginLinearGradientFill(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120);
   *
   * A tiny API method "lf" also exists.
   * @method beginLinearGradientFill
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient
   * drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw
   * the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
   * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginLinearGradientFill = function(colors, ratios, x0, y0, x1, y1) {
    return this._setFill(new G.Fill().linearGradient(colors, ratios, x0, y0, x1, y1));
  };

  /**
   * Begins a radial gradient fill. This ends the current sub-path. For example, the following code defines a red to
   * blue radial gradient centered at (100, 100), with a radius of 50, and draws a circle to display it:
   *
   *      myGraphics.beginRadialGradientFill(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50).drawCircle(100, 100, 50);
   *
   * A tiny API method "rf" also exists.
   * @method beginRadialGradientFill
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 Center position of the inner circle that defines the gradient.
   * @param {Number} y0 Center position of the inner circle that defines the gradient.
   * @param {Number} r0 Radius of the inner circle that defines the gradient.
   * @param {Number} x1 Center position of the outer circle that defines the gradient.
   * @param {Number} y1 Center position of the outer circle that defines the gradient.
   * @param {Number} r1 Radius of the outer circle that defines the gradient.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginRadialGradientFill = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
    return this._setFill(new G.Fill().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1));
  };

  /**
   * Begins a pattern fill using the specified image. This ends the current sub-path. A tiny API method "bf" also
   * exists.
   * @method beginBitmapFill
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
   * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty.
   * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat",
   * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or
   * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat".
   * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation
   * will be applied relative to the parent transform.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginBitmapFill = function(image, repetition, matrix) {
    return this._setFill(new G.Fill(null,matrix).bitmap(image, repetition));
  };

  /**
   * Ends the current sub-path, and begins a new one with no fill. Functionally identical to <code>beginFill(null)</code>.
   * A tiny API method "ef" also exists.
   * @method endFill
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.endFill = function() {
    return this.beginFill();
  };

  /**
   * Sets the stroke style. Like all drawing methods, this can be chained, so you can define
   * the stroke style and color in a single line of code like so:
   *
   *  myGraphics.setStrokeStyle(8,"round").beginStroke("#F00");
   *
   * A tiny API method "ss" also exists.
   * @method setStrokeStyle
   * @param {Number} thickness The width of the stroke.
   * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt,
   * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with
   * the tiny API.
   * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet.
   * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel)
   * for use with the tiny API.
   * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which
   * controls at what point a mitered joint will be clipped.
   * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless
   * of active transformations.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.setStrokeStyle = function(thickness, caps, joints, miterLimit, ignoreScale) {
    this._updateInstructions(true);
    this._strokeStyle = this.command = new G.StrokeStyle(thickness, caps, joints, miterLimit, ignoreScale);

    // ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery:
    if (this._stroke) { this._stroke.ignoreScale = ignoreScale; }
    this._strokeIgnoreScale = ignoreScale;
    return this;
  };
  
  /**
   * Sets or clears the stroke dash pattern.
   *
   *  myGraphics.setStrokeDash([20, 10], 0);
   *
   * A tiny API method `sd` also exists.
   * @method setStrokeDash
   * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap.
   * For example, `[20,10]` would create a pattern of 20 pixel lines with 10 pixel gaps between them.
   * Passing null or an empty array will clear the existing stroke dash.
   * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.setStrokeDash = function(segments, offset) {
    this._updateInstructions(true);
    this._strokeDash = this.command = new G.StrokeDash(segments, offset);
    return this;
  };

  /**
   * Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists.
   * @method beginStroke
   * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to
   * null will result in no stroke.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginStroke = function(color) {
    return this._setStroke(color ? new G.Stroke(color) : null);
  };

  /**
   * Begins a linear gradient stroke defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For
   * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a
   * square to display it:
   *
   *      myGraphics.setStrokeStyle(10).
   *          beginLinearGradientStroke(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120);
   *
   * A tiny API method "ls" also exists.
   * @method beginLinearGradientStroke
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
   * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginLinearGradientStroke = function(colors, ratios, x0, y0, x1, y1) {
    return this._setStroke(new G.Stroke().linearGradient(colors, ratios, x0, y0, x1, y1));
  };

  /**
   * Begins a radial gradient stroke. This ends the current sub-path. For example, the following code defines a red to
   * blue radial gradient centered at (100, 100), with a radius of 50, and draws a rectangle to display it:
   *
   *      myGraphics.setStrokeStyle(10)
   *          .beginRadialGradientStroke(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50)
   *          .drawRect(50, 90, 150, 110);
   *
   * A tiny API method "rs" also exists.
   * @method beginRadialGradientStroke
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color
   * to 100%.
   * @param {Number} x0 Center position of the inner circle that defines the gradient.
   * @param {Number} y0 Center position of the inner circle that defines the gradient.
   * @param {Number} r0 Radius of the inner circle that defines the gradient.
   * @param {Number} x1 Center position of the outer circle that defines the gradient.
   * @param {Number} y1 Center position of the outer circle that defines the gradient.
   * @param {Number} r1 Radius of the outer circle that defines the gradient.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginRadialGradientStroke = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
    return this._setStroke(new G.Stroke().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1));
  };

  /**
   * Begins a pattern fill using the specified image. This ends the current sub-path. Note that unlike bitmap fills,
   * strokes do not currently support a matrix parameter due to limitations in the canvas API. A tiny API method "bs"
   * also exists.
   * @method beginBitmapStroke
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
   * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty.
   * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of
   * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat".
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.beginBitmapStroke = function(image, repetition) {
    // NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width.
    return this._setStroke(new G.Stroke().bitmap(image, repetition));
  };

  /**
   * Ends the current sub-path, and begins a new one with no stroke. Functionally identical to <code>beginStroke(null)</code>.
   * A tiny API method "es" also exists.
   * @method endStroke
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.endStroke = function() {
    return this.beginStroke();
  };

  /**
   * Maps the familiar ActionScript <code>curveTo()</code> method to the functionally similar {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}}
   * method.
   * @method quadraticCurveTo
   * @param {Number} cpx
   * @param {Number} cpy
   * @param {Number} x
   * @param {Number} y
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.curveTo = p.quadraticCurveTo;

  /**
   *
   * Maps the familiar ActionScript <code>drawRect()</code> method to the functionally similar {{#crossLink "Graphics/rect"}}{{/crossLink}}
   * method.
   * @method drawRect
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w Width of the rectangle
   * @param {Number} h Height of the rectangle
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawRect = p.rect;

  /**
   * Draws a rounded rectangle with all corners with the specified radius.
   * @method drawRoundRect
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   * @param {Number} radius Corner radius.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawRoundRect = function(x, y, w, h, radius) {
    return this.drawRoundRectComplex(x, y, w, h, radius, radius, radius, radius);
  };

  /**
   * Draws a rounded rectangle with different corner radii. Supports positive and negative corner radii. A tiny API
   * method "rc" also exists.
   * @method drawRoundRectComplex
   * @param {Number} x The horizontal coordinate to draw the round rect.
   * @param {Number} y The vertical coordinate to draw the round rect.
   * @param {Number} w The width of the round rect.
   * @param {Number} h The height of the round rect.
   * @param {Number} radiusTL Top left corner radius.
   * @param {Number} radiusTR Top right corner radius.
   * @param {Number} radiusBR Bottom right corner radius.
   * @param {Number} radiusBL Bottom left corner radius.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawRoundRectComplex = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) {
    return this.append(new G.RoundRect(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL));
  };

  /**
   * Draws a circle with the specified radius at (x, y).
   *
   *      var g = new createjs.Graphics();
   *      g.setStrokeStyle(1);
   *      g.beginStroke(createjs.Graphics.getRGB(0,0,0));
   *      g.beginFill(createjs.Graphics.getRGB(255,0,0));
   *      g.drawCircle(0,0,3);
   *
   *      var s = new createjs.Shape(g);
   *    s.x = 100;
   *    s.y = 100;
   *
   *      stage.addChild(s);
   *      stage.update();
   *
   * A tiny API method "dc" also exists.
   * @method drawCircle
   * @param {Number} x x coordinate center point of circle.
   * @param {Number} y y coordinate center point of circle.
   * @param {Number} radius Radius of circle.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawCircle = function(x, y, radius) {
    return this.append(new G.Circle(x, y, radius));
  };

  /**
   * Draws an ellipse (oval) with a specified width (w) and height (h). Similar to {{#crossLink "Graphics/drawCircle"}}{{/crossLink}},
   * except the width and height can be different. A tiny API method "de" also exists.
   * @method drawEllipse
   * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
   * which draws from center.
   * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
   * which draws from the center.
   * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this
   * number.
   * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawEllipse = function(x, y, w, h) {
    return this.append(new G.Ellipse(x, y, w, h));
  };

  /**
   * Draws a star if pointSize is greater than 0, or a regular polygon if pointSize is 0 with the specified number of
   * points. For example, the following code will draw a familiar 5 pointed star shape centered at 100, 100 and with a
   * radius of 50:
   *
   *      myGraphics.beginFill("#FF0").drawPolyStar(100, 100, 50, 5, 0.6, -90);
   *      // Note: -90 makes the first point vertical
   *
   * A tiny API method "dp" also exists.
   *
   * @method drawPolyStar
   * @param {Number} x Position of the center of the shape.
   * @param {Number} y Position of the center of the shape.
   * @param {Number} radius The outer radius of the shape.
   * @param {Number} sides The number of points on the star or sides on the polygon.
   * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular
   * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy.
   * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point
   * directly to the right of the center.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.drawPolyStar = function(x, y, radius, sides, pointSize, angle) {
    return this.append(new G.PolyStar(x, y, radius, sides, pointSize, angle));
  };

  // TODO: deprecated.
  /**
   * Removed in favour of using custom command objects with {{#crossLink "Graphics/append"}}{{/crossLink}}.
   * @method inject
   * @deprecated
   **/

  /**
   * Appends a graphics command object to the graphics queue. Command objects expose an "exec" method
   * that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into
   * {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw.
   *
   * This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert
   * built-in or custom graphics commands. For example:
   *
   *    // attach data to our shape, so we can access it during the draw:
   *    myShape.color = "red";
   *
   *    // append a Circle command object:
   *    myShape.graphics.append(new Graphics.Circle(50, 50, 30));
   *
   *    // append a custom command object with an exec method that sets the fill style
   *    // based on the shape's data, and then fills the circle.
   *    myShape.graphics.append({exec:function(ctx, shape) {
   *      ctx.fillStyle = shape.color;
   *      ctx.fill();
   *    }});
   *
   * @method append
   * @param {Object} command A graphics command object exposing an "exec" method.
   * @param {boolean} clean The clean param is primarily for internal use. A value of true indicates that a command does not generate a path that should be stroked or filled.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.append = function(command, clean) {
    this._activeInstructions.push(command);
    this.command = command;
    if (!clean) { this._dirty = true; }
    return this;
  };

  /**
   * Decodes a compact encoded path string into a series of draw instructions.
   * This format is not intended to be human readable, and is meant for use by authoring tools.
   * The format uses a base64 character set, with each character representing 6 bits, to define a series of draw
   * commands.
   *
   * Each command is comprised of a single "header" character followed by a variable number of alternating x and y
   * position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the
   * type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4
   * indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the
   * latter. Bits 5 and 6 are currently unused.
   *
   * Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo)
   * parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the
   * 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed
   * by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the
   * case of move operations which are absolute, this value is a delta from the previous x or y position (as
   * appropriate).
   *
   * For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0.
   * <br />A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per
   * parameter.
   * <br />n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits
   * indicate 1500 tenths of a pixel.
   * <br />AA - 000000000000. Absolute y position of 0.
   * <br />I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter.
   * <br />Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to
   * provide an absolute position of +150.0px.
   * <br />AAA - 000000000000000000. A y delta value of 0.
   *
   * A tiny API method "p" also exists.
   * @method decodePath
   * @param {String} str The path string to decode.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.decodePath = function(str) {
    var instructions = [this.moveTo, this.lineTo, this.quadraticCurveTo, this.bezierCurveTo, this.closePath];
    var paramCount = [2, 2, 4, 6, 0];
    var i=0, l=str.length;
    var params = [];
    var x=0, y=0;
    var base64 = Graphics.BASE_64;

    while (i<l) {
      var c = str.charAt(i);
      var n = base64[c];
      var fi = n>>3; // highest order bits 1-3 code for operation.
      var f = instructions[fi];
      // check that we have a valid instruction & that the unused bits are empty:
      if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); }
      var pl = paramCount[fi];
      if (!fi) { x=y=0; } // move operations reset the position.
      params.length = 0;
      i++;
      var charCount = (n>>2&1)+2;  // 4th header bit indicates number size for this operation.
      for (var p=0; p<pl; p++) {
        var num = base64[str.charAt(i)];
        var sign = (num>>5) ? -1 : 1;
        num = ((num&31)<<6)|(base64[str.charAt(i+1)]);
        if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); }
        num = sign*num/10;
        if (p%2) { x = (num += x); }
        else { y = (num += y); }
        params[p] = num;
        i += charCount;
      }
      f.apply(this,params);
    }
    return this;
  };

  /**
   * Stores all graphics commands so they won't be executed in future draws. Calling store() a second time adds to
   * the existing store. This also affects `drawAsPath()`.
   *
   * This is useful in cases where you are creating vector graphics in an iterative manner (ex. generative art), so
   * that only new graphics need to be drawn (which can provide huge performance benefits), but you wish to retain all
   * of the vector instructions for later use (ex. scaling, modifying, or exporting).
   *
   * Note that calling store() will force the active path (if any) to be ended in a manner similar to changing
   * the fill or stroke.
   *
   * For example, consider a application where the user draws lines with the mouse. As each line segment (or collection of
   * segments) are added to a Shape, it can be rasterized using {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}},
   * and then stored, so that it can be redrawn at a different scale when the application is resized, or exported to SVG.
   *
   *  // set up cache:
   *  myShape.cache(0,0,500,500,scale);
   *
   *  // when the user drags, draw a new line:
   *  myShape.graphics.moveTo(oldX,oldY).lineTo(newX,newY);
   *  // then draw it into the existing cache:
   *  myShape.updateCache("source-over");
   *  // store the new line, so it isn't redrawn next time:
   *  myShape.store();
   *
   *  // then, when the window resizes, we can re-render at a different scale:
   *  // first, unstore all our lines:
   *  myShape.unstore();
   *  // then cache using the new scale:
   *  myShape.cache(0,0,500,500,newScale);
   *  // finally, store the existing commands again:
   *  myShape.store();
   *
   * @method store
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.store = function() {
    this._updateInstructions(true);
    this._storeIndex = this._instructions.length;
    return this;
  };

  /**
   * Unstores any graphics commands that were previously stored using {{#crossLink "Graphics/store"}}{{/crossLink}}
   * so that they will be executed in subsequent draw calls.
   *
   * @method unstore
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.unstore = function() {
    this._storeIndex = 0;
    return this;
  };

  /**
   * Returns a clone of this Graphics instance. Note that the individual command objects are not cloned.
   * @method clone
   * @return {Graphics} A clone of the current Graphics instance.
   **/
  p.clone = function() {
    var o = new Graphics();
    o.command = this.command;
    o._stroke = this._stroke;
    o._strokeStyle = this._strokeStyle;
    o._strokeDash = this._strokeDash;
    o._strokeIgnoreScale = this._strokeIgnoreScale;
    o._fill = this._fill;
    o._instructions = this._instructions.slice();
    o._commitIndex = this._commitIndex;
    o._activeInstructions = this._activeInstructions.slice();
    o._dirty = this._dirty;
    o._storeIndex = this._storeIndex;
    return o;
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Graphics]";
  };


// tiny API:
  /**
   * Shortcut to moveTo.
   * @method mt
   * @param {Number} x The x coordinate the drawing point should move to.
   * @param {Number} y The y coordinate the drawing point should move to.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls).
   * @chainable
   * @protected
   **/
  p.mt = p.moveTo;

  /**
   * Shortcut to lineTo.
   * @method lt
   * @param {Number} x The x coordinate the drawing point should draw to.
   * @param {Number} y The y coordinate the drawing point should draw to.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.lt = p.lineTo;

  /**
   * Shortcut to arcTo.
   * @method at
   * @param {Number} x1
   * @param {Number} y1
   * @param {Number} x2
   * @param {Number} y2
   * @param {Number} radius
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.at = p.arcTo;

  /**
   * Shortcut to bezierCurveTo.
   * @method bt
   * @param {Number} cp1x
   * @param {Number} cp1y
   * @param {Number} cp2x
   * @param {Number} cp2y
   * @param {Number} x
   * @param {Number} y
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.bt = p.bezierCurveTo;

  /**
   * Shortcut to quadraticCurveTo / curveTo.
   * @method qt
   * @param {Number} cpx
   * @param {Number} cpy
   * @param {Number} x
   * @param {Number} y
   * @protected
   * @chainable
   **/
  p.qt = p.quadraticCurveTo;

  /**
   * Shortcut to arc.
   * @method a
   * @param {Number} x
   * @param {Number} y
   * @param {Number} radius
   * @param {Number} startAngle Measured in radians.
   * @param {Number} endAngle Measured in radians.
   * @param {Boolean} anticlockwise
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @protected
   * @chainable
   **/
  p.a = p.arc;

  /**
   * Shortcut to rect.
   * @method r
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w Width of the rectangle
   * @param {Number} h Height of the rectangle
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.r = p.rect;

  /**
   * Shortcut to closePath.
   * @method cp
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.cp = p.closePath;

  /**
   * Shortcut to clear.
   * @method c
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.c = p.clear;

  /**
   * Shortcut to beginFill.
   * @method f
   * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to
   * null will result in no fill.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.f = p.beginFill;

  /**
   * Shortcut to beginLinearGradientFill.
   * @method lf
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient
   * drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw
   * the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
   * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.lf = p.beginLinearGradientFill;

  /**
   * Shortcut to beginRadialGradientFill.
   * @method rf
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 Center position of the inner circle that defines the gradient.
   * @param {Number} y0 Center position of the inner circle that defines the gradient.
   * @param {Number} r0 Radius of the inner circle that defines the gradient.
   * @param {Number} x1 Center position of the outer circle that defines the gradient.
   * @param {Number} y1 Center position of the outer circle that defines the gradient.
   * @param {Number} r1 Radius of the outer circle that defines the gradient.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.rf = p.beginRadialGradientFill;

  /**
   * Shortcut to beginBitmapFill.
   * @method bf
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
   * as the pattern.
   * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat",
   * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or
   * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat".
   * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation
   * will be applied relative to the parent transform.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.bf = p.beginBitmapFill;

  /**
   * Shortcut to endFill.
   * @method ef
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.ef = p.endFill;

  /**
   * Shortcut to setStrokeStyle.
   * @method ss
   * @param {Number} thickness The width of the stroke.
   * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt,
   * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with
   * the tiny API.
   * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet.
   * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel)
   * for use with the tiny API.
   * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which
   * controls at what point a mitered joint will be clipped.
   * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless
   * of active transformations.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.ss = p.setStrokeStyle;
  
  /**
   * Shortcut to setStrokeDash.
   * @method sd
   * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap.
   * For example, [20,10] would create a pattern of 20 pixel lines with 10 pixel gaps between them.
   * Passing null or an empty array will clear any existing dash.
   * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.sd = p.setStrokeDash;

  /**
   * Shortcut to beginStroke.
   * @method s
   * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to
   * null will result in no stroke.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.s = p.beginStroke;

  /**
   * Shortcut to beginLinearGradientStroke.
   * @method ls
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
   * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
   * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
   * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.ls = p.beginLinearGradientStroke;

  /**
   * Shortcut to beginRadialGradientStroke.
   * @method rs
   * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
   * a gradient drawing from red to blue.
   * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
   * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color
   * to 100%.
   * @param {Number} x0 Center position of the inner circle that defines the gradient.
   * @param {Number} y0 Center position of the inner circle that defines the gradient.
   * @param {Number} r0 Radius of the inner circle that defines the gradient.
   * @param {Number} x1 Center position of the outer circle that defines the gradient.
   * @param {Number} y1 Center position of the outer circle that defines the gradient.
   * @param {Number} r1 Radius of the outer circle that defines the gradient.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.rs = p.beginRadialGradientStroke;

  /**
   * Shortcut to beginBitmapStroke.
   * @method bs
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
   * as the pattern.
   * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of
   * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat".
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.bs = p.beginBitmapStroke;

  /**
   * Shortcut to endStroke.
   * @method es
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.es = p.endStroke;

  /**
   * Shortcut to drawRect.
   * @method dr
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w Width of the rectangle
   * @param {Number} h Height of the rectangle
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.dr = p.drawRect;

  /**
   * Shortcut to drawRoundRect.
   * @method rr
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   * @param {Number} radius Corner radius.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.rr = p.drawRoundRect;

  /**
   * Shortcut to drawRoundRectComplex.
   * @method rc
   * @param {Number} x The horizontal coordinate to draw the round rect.
   * @param {Number} y The vertical coordinate to draw the round rect.
   * @param {Number} w The width of the round rect.
   * @param {Number} h The height of the round rect.
   * @param {Number} radiusTL Top left corner radius.
   * @param {Number} radiusTR Top right corner radius.
   * @param {Number} radiusBR Bottom right corner radius.
   * @param {Number} radiusBL Bottom left corner radius.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.rc = p.drawRoundRectComplex;

  /**
   * Shortcut to drawCircle.
   * @method dc
   * @param {Number} x x coordinate center point of circle.
   * @param {Number} y y coordinate center point of circle.
   * @param {Number} radius Radius of circle.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.dc = p.drawCircle;

  /**
   * Shortcut to drawEllipse.
   * @method de
   * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
   * which draws from center.
   * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
   * which draws from the center.
   * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this
   * number.
   * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.de = p.drawEllipse;

  /**
   * Shortcut to drawPolyStar.
   * @method dp
   * @param {Number} x Position of the center of the shape.
   * @param {Number} y Position of the center of the shape.
   * @param {Number} radius The outer radius of the shape.
   * @param {Number} sides The number of points on the star or sides on the polygon.
   * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular
   * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy.
   * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point
   * directly to the right of the center.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.dp = p.drawPolyStar;

  /**
   * Shortcut to decodePath.
   * @method p
   * @param {String} str The path string to decode.
   * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
   * @chainable
   * @protected
   **/
  p.p = p.decodePath;


// private methods:
  /**
   * @method _updateInstructions
   * @param commit
   * @protected
   **/
  p._updateInstructions = function(commit) {
    var instr = this._instructions, active = this._activeInstructions, commitIndex = this._commitIndex;

    if (this._dirty && active.length) {
      instr.length = commitIndex; // remove old, uncommitted commands
      instr.push(Graphics.beginCmd);

      var l = active.length, ll = instr.length;
      instr.length = ll+l;
      for (var i=0; i<l; i++) { instr[i+ll] = active[i]; }

      if (this._fill) { instr.push(this._fill); }
      if (this._stroke) {
        // doesn't need to be re-applied if it hasn't changed.
        if (this._strokeDash !== this._oldStrokeDash) {
          this._oldStrokeDash = this._strokeDash;
          instr.push(this._strokeDash);
        }
        if (this._strokeStyle !== this._oldStrokeStyle) {
          this._oldStrokeStyle = this._strokeStyle;
          instr.push(this._strokeStyle);
        }
        instr.push(this._stroke);
      }

      this._dirty = false;
    }

    if (commit) {
      active.length = 0;
      this._commitIndex = instr.length;
    }
  };

  /**
   * @method _setFill
   * @param fill
   * @protected
   **/
  p._setFill = function(fill) {
    this._updateInstructions(true);
    this.command = this._fill = fill;
    return this;
  };

  /**
   * @method _setStroke
   * @param stroke
   * @protected
   **/
  p._setStroke = function(stroke) {
    this._updateInstructions(true);
    if (this.command = this._stroke = stroke) {
      stroke.ignoreScale = this._strokeIgnoreScale;
    }
    return this;
  };

// Command Objects:
  /**
   * @namespace Graphics
   */
  /**
   * Graphics command object. See {{#crossLink "Graphics/lineTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class LineTo
   * @constructor
   * @param {Number} x
   * @param {Number} y
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.LineTo = function(x, y) {
    this.x = x; this.y = y;
  }).prototype.exec = function(ctx) { ctx.lineTo(this.x,this.y); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/moveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class MoveTo
   * @constructor
   * @param {Number} x
   * @param {Number} y
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.MoveTo = function(x, y) {
    this.x = x; this.y = y;
  }).prototype.exec = function(ctx) { ctx.moveTo(this.x, this.y); };


  /**
   * Graphics command object. See {{#crossLink "Graphics/arcTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class ArcTo
   * @constructor
   * @param {Number} x1
   * @param {Number} y1
   * @param {Number} x2
   * @param {Number} y2
   * @param {Number} radius
   **/
  /**
   * @property x1
   * @type Number
   */
  /**
   * @property y1
   * @type Number
   */
  /**
   * @property x2
   * @type Number
   */
  /**
   * @property y2
   * @type Number
   */
  /**
   * @property radius
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.ArcTo = function(x1, y1, x2, y2, radius) {
    this.x1 = x1; this.y1 = y1;
    this.x2 = x2; this.y2 = y2;
    this.radius = radius;
  }).prototype.exec = function(ctx) { ctx.arcTo(this.x1, this.y1, this.x2, this.y2, this.radius); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/arc"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Arc
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} radius
   * @param {Number} startAngle
   * @param {Number} endAngle
   * @param {Number} anticlockwise
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property radius
   * @type Number
   */
  /**
   * @property startAngle
   * @type Number
   */
  /**
   * @property endAngle
   * @type Number
   */
  /**
   * @property anticlockwise
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.Arc = function(x, y, radius, startAngle, endAngle, anticlockwise) {
    this.x = x; this.y = y;
    this.radius = radius;
    this.startAngle = startAngle; this.endAngle = endAngle;
    this.anticlockwise = !!anticlockwise;
  }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle, this.anticlockwise); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class QuadraticCurveTo
   * @constructor
   * @param {Number} cpx
   * @param {Number} cpy
   * @param {Number} x
   * @param {Number} y
   **/
  /**
   * @property cpx
   * @type Number
   */
  /**
   * @property cpy
   * @type Number
   */
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.QuadraticCurveTo = function(cpx, cpy, x, y) {
    this.cpx = cpx; this.cpy = cpy;
    this.x = x; this.y = y;
  }).prototype.exec = function(ctx) { ctx.quadraticCurveTo(this.cpx, this.cpy, this.x, this.y); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class BezierCurveTo
   * @constructor
   * @param {Number} cp1x
   * @param {Number} cp1y
   * @param {Number} cp2x
   * @param {Number} cp2y
   * @param {Number} x
   * @param {Number} y
   **/
  /**
   * @property cp1x
   * @type Number
   */
  /**
   * @property cp1y
   * @type Number
   */
  /**
   * @property cp2x
   * @type Number
   */
  /**
   * @property cp2y
   * @type Number
   */
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.BezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
    this.cp1x = cp1x; this.cp1y = cp1y;
    this.cp2x = cp2x; this.cp2y = cp2y;
    this.x = x; this.y = y;
  }).prototype.exec = function(ctx) { ctx.bezierCurveTo(this.cp1x, this.cp1y, this.cp2x, this.cp2y, this.x, this.y); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/rect"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Rect
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property w
   * @type Number
   */
  /**
   * @property h
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.Rect = function(x, y, w, h) {
    this.x = x; this.y = y;
    this.w = w; this.h = h;
  }).prototype.exec = function(ctx) { ctx.rect(this.x, this.y, this.w, this.h); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/closePath"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class ClosePath
   * @constructor
   **/
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.ClosePath = function() {
  }).prototype.exec = function(ctx) { ctx.closePath(); };

  /**
   * Graphics command object to begin a new path. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class BeginPath
   * @constructor
   **/
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.BeginPath = function() {
  }).prototype.exec = function(ctx) { ctx.beginPath(); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/beginFill"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Fill
   * @constructor
   * @param {Object} style A valid Context2D fillStyle.
   * @param {Matrix2D} matrix
   **/
  /**
   * A valid Context2D fillStyle.
   * @property style
   * @type Object
   */
  /**
   * @property matrix
   * @type Matrix2D
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  p = (G.Fill = function(style, matrix) {
    this.style = style;
    this.matrix = matrix;
  }).prototype;
  p.exec = function(ctx) {
    if (!this.style) { return; }
    ctx.fillStyle = this.style;
    var mtx = this.matrix;
    if (mtx) { ctx.save(); ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); }
    ctx.fill();
    if (mtx) { ctx.restore(); }
  };
  /**
   * Creates a linear gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} for more information.
   * @method linearGradient
   * @param {Array} colors
   * @param {Array} ratios
   * @param {Number} x0
   * @param {Number} y0
   * @param {Number} x1
   * @param {Number} y1
   * @return {Fill} Returns this Fill object for chaining or assignment.
   */
  p.linearGradient = function(colors, ratios, x0, y0, x1, y1) {
    var o = this.style =  Graphics._ctx.createLinearGradient(x0, y0, x1, y1);
    for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); }
    o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, x1:x1, y1:y1, type:"linear"};
    return this;
  };
  /**
   * Creates a radial gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} for more information.
   * @method radialGradient
   * @param {Array} colors
   * @param {Array} ratios
   * @param {Number} x0
   * @param {Number} y0
   * @param {Number} r0
   * @param {Number} x1
   * @param {Number} y1
   * @param {Number} r1
   * @return {Fill} Returns this Fill object for chaining or assignment.
   */
  p.radialGradient = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
    var o = this.style =  Graphics._ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
    for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); }
    o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, r0:r0, x1:x1, y1:y1, r1:r1, type:"radial"};
    return this;
  };
  /**
   * Creates a bitmap fill style and assigns it to the {{#crossLink "Fill/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} for more information.
   * @method bitmap
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image  Must be loaded prior to creating a bitmap fill, or the fill will be empty.
   * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat.
   * @return {Fill} Returns this Fill object for chaining or assignment.
   */
  p.bitmap = function(image, repetition) {
    if (image.naturalWidth || image.getContext || image.readyState >= 2) {
      var o = this.style = Graphics._ctx.createPattern(image, repetition || "");
      o.props = {image: image, repetition: repetition, type: "bitmap"};
    }
    return this;
  };
  p.path = false;

  /**
   * Graphics command object. See {{#crossLink "Graphics/beginStroke"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Stroke
   * @constructor
   * @param {Object} style A valid Context2D fillStyle.
   * @param {Boolean} ignoreScale
   **/
  /**
   * A valid Context2D strokeStyle.
   * @property style
   * @type Object
   */
  /**
   * @property ignoreScale
   * @type Boolean
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  p = (G.Stroke = function(style, ignoreScale) {
    this.style = style;
    this.ignoreScale = ignoreScale;
  }).prototype;
  p.exec = function(ctx) {
    if (!this.style) { return; }
    ctx.strokeStyle = this.style;
    if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); }
    ctx.stroke();
    if (this.ignoreScale) { ctx.restore(); }
  };
  /**
   * Creates a linear gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} for more information.
   * @method linearGradient
   * @param {Array} colors
   * @param {Array} ratios
   * @param {Number} x0
   * @param {Number} y0
   * @param {Number} x1
   * @param {Number} y1
   * @return {Fill} Returns this Stroke object for chaining or assignment.
   */
  p.linearGradient = G.Fill.prototype.linearGradient;
  /**
   * Creates a radial gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} for more information.
   * @method radialGradient
   * @param {Array} colors
   * @param {Array} ratios
   * @param {Number} x0
   * @param {Number} y0
   * @param {Number} r0
   * @param {Number} x1
   * @param {Number} y1
   * @param {Number} r1
   * @return {Fill} Returns this Stroke object for chaining or assignment.
   */
  p.radialGradient = G.Fill.prototype.radialGradient;
  /**
   * Creates a bitmap fill style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
   * See {{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} for more information.
   * @method bitmap
   * @param {HTMLImageElement} image
   * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat.
   * @return {Fill} Returns this Stroke object for chaining or assignment.
   */
  p.bitmap = G.Fill.prototype.bitmap;
  p.path = false;

  /**
   * Graphics command object. See {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class StrokeStyle
   * @constructor
   * @param {Number} width
   * @param {String} [caps]
   * @param {String} [joints]
   * @param {Number} [miterLimit]
   **/
  /**
   * @property width
   * @type Number
   */
  /**
   * One of: butt, round, square
   * @property caps
   * @type String
   */
  /**
   * One of: round, bevel, miter
   * @property joints
   * @type String
   */
  /**
   * @property miterLimit
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  p = (G.StrokeStyle = function(width, caps, joints, miterLimit) {
    this.width = width;
    this.caps = caps;
    this.joints = joints;
    this.miterLimit = miterLimit;
  }).prototype;
  p.exec = function(ctx) {
    ctx.lineWidth = (this.width == null ? "1" : this.width);
    ctx.lineCap = (this.caps == null ? "butt" : (isNaN(this.caps) ? this.caps : Graphics.STROKE_CAPS_MAP[this.caps]));
    ctx.lineJoin = (this.joints == null ? "miter" : (isNaN(this.joints) ? this.joints : Graphics.STROKE_JOINTS_MAP[this.joints]));
    ctx.miterLimit = (this.miterLimit == null ? "10" : this.miterLimit);
  };
  p.path = false;
  
  /**
   * Graphics command object. See {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class StrokeDash
   * @constructor
   * @param {Array} [segments]
   * @param {Number} [offset=0]
   **/
  /**
   * @property segments
   * @type Array
   */
  /**
   * @property offset
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.StrokeDash = function(segments, offset) {
    this.segments = segments;
    this.offset = offset||0;
  }).prototype.exec = function(ctx) {
    if (ctx.setLineDash) { // feature detection.
      ctx.setLineDash(this.segments|| G.StrokeDash.EMPTY_SEGMENTS); // instead of [] to reduce churn.
      ctx.lineDashOffset = this.offset||0;
    }
  };
  /**
   * The default value for segments (ie. no dash).
   * @property EMPTY_SEGMENTS
   * @static
   * @final
   * @readonly
   * @protected
   * @type {Array}
   **/
  G.StrokeDash.EMPTY_SEGMENTS = [];

  /**
   * Graphics command object. See {{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class RoundRect
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   * @param {Number} radiusTL
   * @param {Number} radiusTR
   * @param {Number} radiusBR
   * @param {Number} radiusBL
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property w
   * @type Number
   */
  /**
   * @property h
   * @type Number
   */
  /**
   * @property radiusTL
   * @type Number
   */
  /**
   * @property radiusTR
   * @type Number
   */
  /**
   * @property radiusBR
   * @type Number
   */
  /**
   * @property radiusBL
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.RoundRect = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) {
    this.x = x; this.y = y;
    this.w = w; this.h = h;
    this.radiusTL = radiusTL; this.radiusTR = radiusTR;
    this.radiusBR = radiusBR; this.radiusBL = radiusBL;
  }).prototype.exec = function(ctx) {
    var max = (w<h?w:h)/2;
    var mTL=0, mTR=0, mBR=0, mBL=0;
    var x = this.x, y = this.y, w = this.w, h = this.h;
    var rTL = this.radiusTL, rTR = this.radiusTR, rBR = this.radiusBR, rBL = this.radiusBL;

    if (rTL < 0) { rTL *= (mTL=-1); }
    if (rTL > max) { rTL = max; }
    if (rTR < 0) { rTR *= (mTR=-1); }
    if (rTR > max) { rTR = max; }
    if (rBR < 0) { rBR *= (mBR=-1); }
    if (rBR > max) { rBR = max; }
    if (rBL < 0) { rBL *= (mBL=-1); }
    if (rBL > max) { rBL = max; }

    ctx.moveTo(x+w-rTR, y);
    ctx.arcTo(x+w+rTR*mTR, y-rTR*mTR, x+w, y+rTR, rTR);
    ctx.lineTo(x+w, y+h-rBR);
    ctx.arcTo(x+w+rBR*mBR, y+h+rBR*mBR, x+w-rBR, y+h, rBR);
    ctx.lineTo(x+rBL, y+h);
    ctx.arcTo(x-rBL*mBL, y+h+rBL*mBL, x, y+h-rBL, rBL);
    ctx.lineTo(x, y+rTL);
    ctx.arcTo(x-rTL*mTL, y-rTL*mTL, x+rTL, y, rTL);
    ctx.closePath();
  };

  /**
   * Graphics command object. See {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Circle
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} radius
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property radius
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.Circle = function(x, y, radius) {
    this.x = x; this.y = y;
    this.radius = radius;
  }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); };

  /**
   * Graphics command object. See {{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class Ellipse
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property w
   * @type Number
   */
  /**
   * @property h
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.Ellipse = function(x, y, w, h) {
    this.x = x; this.y = y;
    this.w = w; this.h = h;
  }).prototype.exec = function(ctx) {
    var x = this.x, y = this.y;
    var w = this.w, h = this.h;

    var k = 0.5522848;
    var ox = (w / 2) * k;
    var oy = (h / 2) * k;
    var xe = x + w;
    var ye = y + h;
    var xm = x + w / 2;
    var ym = y + h / 2;

    ctx.moveTo(x, ym);
    ctx.bezierCurveTo(x, ym-oy, xm-ox, y, xm, y);
    ctx.bezierCurveTo(xm+ox, y, xe, ym-oy, xe, ym);
    ctx.bezierCurveTo(xe, ym+oy, xm+ox, ye, xm, ye);
    ctx.bezierCurveTo(xm-ox, ye, x, ym+oy, x, ym);
  };

  /**
   * Graphics command object. See {{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
   * @class PolyStar
   * @constructor
   * @param {Number} x
   * @param {Number} y
   * @param {Number} radius
   * @param {Number} sides
   * @param {Number} pointSize
   * @param {Number} angle
   **/
  /**
   * @property x
   * @type Number
   */
  /**
   * @property y
   * @type Number
   */
  /**
   * @property radius
   * @type Number
   */
  /**
   * @property sides
   * @type Number
   */
  /**
   * @property pointSize
   * @type Number
   */
  /**
   * @property angle
   * @type Number
   */
  /**
   * @method exec
   * @param {CanvasRenderingContext2D} ctx
   */
  (G.PolyStar = function(x, y, radius, sides, pointSize, angle) {
    this.x = x; this.y = y;
    this.radius = radius;
    this.sides = sides;
    this.pointSize = pointSize;
    this.angle = angle;
  }).prototype.exec = function(ctx) {
    var x = this.x, y = this.y;
    var radius = this.radius;
    var angle = (this.angle||0)/180*Math.PI;
    var sides = this.sides;
    var ps = 1-(this.pointSize||0);
    var a = Math.PI/sides;

    ctx.moveTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius);
    for (var i=0; i<sides; i++) {
      angle += a;
      if (ps != 1) {
        ctx.lineTo(x+Math.cos(angle)*radius*ps, y+Math.sin(angle)*radius*ps);
      }
      angle += a;
      ctx.lineTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius);
    }
    ctx.closePath();
  };

  // docced above.
  Graphics.beginCmd = new G.BeginPath(); // so we don't have to instantiate multiple instances.


  createjs.Graphics = Graphics;
}());

//##############################################################################
// DisplayObject.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * DisplayObject is an abstract class that should not be constructed directly. Instead construct subclasses such as
   * {{#crossLink "Container"}}{{/crossLink}}, {{#crossLink "Bitmap"}}{{/crossLink}}, and {{#crossLink "Shape"}}{{/crossLink}}.
   * DisplayObject is the base class for all display classes in the EaselJS library. It defines the core properties and
   * methods that are shared between all display objects, such as transformation properties (x, y, scaleX, scaleY, etc),
   * caching, and mouse handlers.
   * @class DisplayObject
   * @extends EventDispatcher
   * @constructor
   **/
  function DisplayObject() {
    this.EventDispatcher_constructor();
    
    
  // public properties:
    /**
     * The alpha (transparency) for this display object. 0 is fully transparent, 1 is fully opaque.
     * @property alpha
     * @type {Number}
     * @default 1
     **/
    this.alpha = 1;
  
    /**
     * If a cache is active, this returns the canvas that holds the cached version of this display object. See {{#crossLink "cache"}}{{/crossLink}}
     * for more information.
     * @property cacheCanvas
     * @type {HTMLCanvasElement | Object}
     * @default null
     * @readonly
     **/
    this.cacheCanvas = null;
  
    /**
     * Returns an ID number that uniquely identifies the current cache for this display object. This can be used to
     * determine if the cache has changed since a previous check.
     * @property cacheID
     * @type {Number}
     * @default 0
     */
    this.cacheID = 0;
  
    /**
     * Unique ID for this display object. Makes display objects easier for some uses.
     * @property id
     * @type {Number}
     * @default -1
     **/
    this.id = createjs.UID.get();
  
    /**
     * Indicates whether to include this object when running mouse interactions. Setting this to `false` for children
     * of a {{#crossLink "Container"}}{{/crossLink}} will cause events on the Container to not fire when that child is
     * clicked. Setting this property to `false` does not prevent the {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}
     * method from returning the child.
     *
     * <strong>Note:</strong> In EaselJS 0.7.0, the mouseEnabled property will not work properly with nested Containers. Please
     * check out the latest NEXT version in <a href="https://github.com/CreateJS/EaselJS/tree/master/lib">GitHub</a> for an updated version with this issue resolved. The fix will be
     * provided in the next release of EaselJS.
     * @property mouseEnabled
     * @type {Boolean}
     * @default true
     **/
    this.mouseEnabled = true;
    
    /**
     * If false, the tick will not run on this display object (or its children). This can provide some performance benefits.
     * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates
     * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling).
     * @property tickEnabled
     * @type Boolean
     * @default true
     **/
    this.tickEnabled = true;
  
    /**
     * An optional name for this display object. Included in {{#crossLink "DisplayObject/toString"}}{{/crossLink}} . Useful for
     * debugging.
     * @property name
     * @type {String}
     * @default null
     **/
    this.name = null;
  
    /**
     * A reference to the {{#crossLink "Container"}}{{/crossLink}} or {{#crossLink "Stage"}}{{/crossLink}} object that
     * contains this display object, or null if it has not been added
     * to one.
     * @property parent
     * @final
     * @type {Container}
     * @default null
     * @readonly
     **/
    this.parent = null;
  
    /**
     * The left offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate
     * around its center, you would set regX and {{#crossLink "DisplayObject/regY:property"}}{{/crossLink}} to 50.
     * @property regX
     * @type {Number}
     * @default 0
     **/
    this.regX = 0;
  
    /**
     * The y offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate around
     * its center, you would set {{#crossLink "DisplayObject/regX:property"}}{{/crossLink}} and regY to 50.
     * @property regY
     * @type {Number}
     * @default 0
     **/
    this.regY = 0;
  
    /**
     * The rotation in degrees for this display object.
     * @property rotation
     * @type {Number}
     * @default 0
     **/
    this.rotation = 0;
  
    /**
     * The factor to stretch this display object horizontally. For example, setting scaleX to 2 will stretch the display
     * object to twice its nominal width. To horizontally flip an object, set the scale to a negative number.
     * @property scaleX
     * @type {Number}
     * @default 1
     **/
    this.scaleX = 1;
  
    /**
     * The factor to stretch this display object vertically. For example, setting scaleY to 0.5 will stretch the display
     * object to half its nominal height. To vertically flip an object, set the scale to a negative number.
     * @property scaleY
     * @type {Number}
     * @default 1
     **/
    this.scaleY = 1;
  
    /**
     * The factor to skew this display object horizontally.
     * @property skewX
     * @type {Number}
     * @default 0
     **/
    this.skewX = 0;
  
    /**
     * The factor to skew this display object vertically.
     * @property skewY
     * @type {Number}
     * @default 0
     **/
    this.skewY = 0;
  
    /**
     * A shadow object that defines the shadow to render on this display object. Set to `null` to remove a shadow. If
     * null, this property is inherited from the parent container.
     * @property shadow
     * @type {Shadow}
     * @default null
     **/
    this.shadow = null;
  
    /**
     * Indicates whether this display object should be rendered to the canvas and included when running the Stage
     * {{#crossLink "Stage/getObjectsUnderPoint"}}{{/crossLink}} method.
     * @property visible
     * @type {Boolean}
     * @default true
     **/
    this.visible = true;
  
    /**
     * The x (horizontal) position of the display object, relative to its parent.
     * @property x
     * @type {Number}
     * @default 0
     **/
    this.x = 0;
  
    /** The y (vertical) position of the display object, relative to its parent.
     * @property y
     * @type {Number}
     * @default 0
     **/
    this.y = 0;
    
    /**
     * If set, defines the transformation for this display object, overriding all other transformation properties
     * (x, y, rotation, scale, skew).
     * @property transformMatrix
     * @type {Matrix2D}
     * @default null
     **/
    this.transformMatrix = null;
    
    /**
     * The composite operation indicates how the pixels of this display object will be composited with the elements
     * behind it. If `null`, this property is inherited from the parent container. For more information, read the
     * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing">
     * whatwg spec on compositing</a>.
     * @property compositeOperation
     * @type {String}
     * @default null
     **/
    this.compositeOperation = null;
  
    /**
     * Indicates whether the display object should be drawn to a whole pixel when
     * {{#crossLink "Stage/snapToPixelEnabled"}}{{/crossLink}} is true. To enable/disable snapping on whole
     * categories of display objects, set this value on the prototype (Ex. Text.prototype.snapToPixel = true).
     * @property snapToPixel
     * @type {Boolean}
     * @default true
     **/
    this.snapToPixel = true;
  
    /**
     * An array of Filter objects to apply to this display object. Filters are only applied / updated when {{#crossLink "cache"}}{{/crossLink}}
     * or {{#crossLink "updateCache"}}{{/crossLink}} is called on the display object, and only apply to the area that is
     * cached.
     * @property filters
     * @type {Array}
     * @default null
     **/
    this.filters = null;
    
    /**
     * A Shape instance that defines a vector mask (clipping path) for this display object.  The shape's transformation
     * will be applied relative to the display object's parent coordinates (as if it were a child of the parent).
     * @property mask
     * @type {Shape}
     * @default null
     */
    this.mask = null;
    
    /**
     * A display object that will be tested when checking mouse interactions or testing {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}.
     * The hit area will have its transformation applied relative to this display object's coordinate space (as though
     * the hit test object were a child of this display object and relative to its regX/Y). The hitArea will be tested
     * using only its own `alpha` value regardless of the alpha value on the target display object, or the target's
     * ancestors (parents).
     * 
     * If set on a {{#crossLink "Container"}}{{/crossLink}}, children of the Container will not receive mouse events.
     * This is similar to setting {{#crossLink "mouseChildren"}}{{/crossLink}} to false.
     *
     * Note that hitArea is NOT currently used by the `hitTest()` method, nor is it supported for {{#crossLink "Stage"}}{{/crossLink}}.
     * @property hitArea
     * @type {DisplayObject}
     * @default null
     */
    this.hitArea = null;
    
    /**
     * A CSS cursor (ex. "pointer", "help", "text", etc) that will be displayed when the user hovers over this display
     * object. You must enable mouseover events using the {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}} method to
     * use this property. Setting a non-null cursor on a Container will override the cursor set on its descendants.
     * @property cursor
     * @type {String}
     * @default null
     */
    this.cursor = null;
  
  
  // private properties:
    /**
     * @property _cacheOffsetX
     * @protected
     * @type {Number}
     * @default 0
     **/
    this._cacheOffsetX = 0;
  
    /**
     * @property _cacheOffsetY
     * @protected
     * @type {Number}
     * @default 0
     **/
    this._cacheOffsetY = 0;
    
    /**
     * @property _filterOffsetX
     * @protected
     * @type {Number}
     * @default 0
     **/
    this._filterOffsetX = 0;
    
    /**
     * @property _filterOffsetY
     * @protected
     * @type {Number}
     * @default 0
     **/
    this._filterOffsetY = 0;
    
    /**
     * @property _cacheScale
     * @protected
     * @type {Number}
     * @default 1
     **/
    this._cacheScale = 1;
  
    /**
    * @property _cacheDataURLID
    * @protected
    * @type {Number}
    * @default 0
    */
    this._cacheDataURLID = 0;
    
    /**
    * @property _cacheDataURL
    * @protected
    * @type {String}
    * @default null
    */
    this._cacheDataURL = null;
  
    /**
     * @property _props
     * @protected
     * @type {DisplayObject}
     * @default null
     **/
    this._props = new createjs.DisplayProps();
  
    /**
     * @property _rectangle
     * @protected
     * @type {Rectangle}
     * @default null
     **/
    this._rectangle = new createjs.Rectangle();
  
    /**
     * @property _bounds
     * @protected
     * @type {Rectangle}
     * @default null
     **/
    this._bounds = null;
  }
  var p = createjs.extend(DisplayObject, createjs.EventDispatcher);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
  
// static properties:
  /**
   * Listing of mouse event names. Used in _hasMouseEventListener.
   * @property _MOUSE_EVENTS
   * @protected
   * @static
   * @type {Array}
   **/
  DisplayObject._MOUSE_EVENTS = ["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"];

  /**
   * Suppresses errors generated when using features like hitTest, mouse events, and {{#crossLink "getObjectsUnderPoint"}}{{/crossLink}}
   * with cross domain content.
   * @property suppressCrossDomainErrors
   * @static
   * @type {Boolean}
   * @default false
   **/
  DisplayObject.suppressCrossDomainErrors = false;
  
  /**
   * @property _snapToPixelEnabled
   * @protected
   * @static
   * @type {Boolean}
   * @default false
   **/
  DisplayObject._snapToPixelEnabled = false; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access.

  /**
   * @property _hitTestCanvas
   * @type {HTMLCanvasElement | Object}
   * @static
   * @protected
   **/
  /**
   * @property _hitTestContext
   * @type {CanvasRenderingContext2D}
   * @static
   * @protected
   **/
  var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); // prevent errors on load in browsers without canvas.
  if (canvas.getContext) {
    DisplayObject._hitTestCanvas = canvas;
    DisplayObject._hitTestContext = canvas.getContext("2d");
    canvas.width = canvas.height = 1;
  }

  /**
   * @property _nextCacheID
   * @type {Number}
   * @static
   * @protected
   **/
  DisplayObject._nextCacheID = 1;


// events:
  /**
   * Dispatched when the user presses their left mouse button over the display object. See the 
   * {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event mousedown
   * @since 0.6.0
   */
   
  /**
   * Dispatched when the user presses their left mouse button and then releases it while over the display object.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event click
   * @since 0.6.0
   */
   
  /**
   * Dispatched when the user double clicks their left mouse button over this display object.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event dblclick
   * @since 0.6.0
   */
   
  /**
   * Dispatched when the user's mouse enters this display object. This event must be enabled using 
   * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event mouseover
   * @since 0.6.0
   */

  /**
   * Dispatched when the user's mouse leaves this display object. This event must be enabled using 
   * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event mouseout
   * @since 0.6.0
   */
   
  /**
   * This event is similar to {{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}, with the following
   * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an
   * aggregate of their content.
   * 
   * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over
   * shapeA and then directly on to shapeB. With a listener for {{#crossLink "mouseover:event"}}{{/crossLink}} on
   * myContainer, two events would be received, each targeting a child element:<OL>
   * <LI>when the mouse enters shapeA (target=shapeA)</LI>
   * <LI>when the mouse enters shapeB (target=shapeB)</LI>
   * </OL>
   * However, with a listener for "rollover" instead, only a single event is received when the mouse first enters
   * the aggregate myContainer content (target=myContainer).
   * 
   * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event rollover
   * @since 0.7.0
   */
   
  /**
   * This event is similar to {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}, with the following
   * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an
   * aggregate of their content.
   * 
   * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over
   * shapeA, then directly on to shapeB, then off both. With a listener for {{#crossLink "mouseout:event"}}{{/crossLink}}
   * on myContainer, two events would be received, each targeting a child element:<OL>
   * <LI>when the mouse leaves shapeA (target=shapeA)</LI>
   * <LI>when the mouse leaves shapeB (target=shapeB)</LI>
   * </OL>
   * However, with a listener for "rollout" instead, only a single event is received when the mouse leaves
   * the aggregate myContainer content (target=myContainer).
   * 
   * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event rollout
   * @since 0.7.0
   */
   
  /**
   * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressmove
   * event will be generated on that object whenever the mouse moves until the mouse press is released. This can be
   * useful for dragging and similar operations.
   * @event pressmove
   * @since 0.7.0
   */
   
  /**
   * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressup event
   * will be generated on that object when that mouse press is released. This can be useful for dragging and similar
   * operations.
   * @event pressup
   * @since 0.7.0
   */
   
  /**
   * Dispatched when the display object is added to a parent container.
   * @event added
   */
   
  /**
   * Dispatched when the display object is removed from its parent container.
   * @event removed
   */
   
  /**
   * Dispatched on each display object on a stage whenever the stage updates. This occurs immediately before the
   * rendering (draw) pass. When {{#crossLink "Stage/update"}}{{/crossLink}} is called, first all display objects on
   * the stage dispatch the tick event, then all of the display objects are drawn to stage. Children will have their
   * {{#crossLink "tick:event"}}{{/crossLink}} event dispatched in order of their depth prior to the event being
   * dispatched on their parent.
   * @event tick
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {Array} params An array containing any arguments that were passed to the Stage.update() method. For
   *      example if you called stage.update("hello"), then the params would be ["hello"].
   * @since 0.6.0
   */
  
  
// getter / setters:
  /**
   * Use the {{#crossLink "DisplayObject/stage:property"}}{{/crossLink}} property instead.
   * @method getStage
   * @return {Stage}
   * @deprecated
   **/
  p.getStage = function() {
    // uses dynamic access to avoid circular dependencies;
    var o = this, _Stage = createjs["Stage"];
    while (o.parent) { o = o.parent; }
    if (o instanceof _Stage) { return o; }
    return null;
  };

  /**
   * Returns the Stage instance that this display object will be rendered on, or null if it has not been added to one.
   * @property stage
   * @type {Stage}
   * @readonly
   **/
  try {
    Object.defineProperties(p, {
      stage: { get: p.getStage }
    });
  } catch (e) {}


// public methods:
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0);
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns <code>true</code> if the draw was handled (useful for overriding functionality).
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example,
   * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself).
   * @return {Boolean}
   **/
  p.draw = function(ctx, ignoreCache) {
    var cacheCanvas = this.cacheCanvas;
    if (ignoreCache || !cacheCanvas) { return false; }
    var scale = this._cacheScale;
    ctx.drawImage(cacheCanvas, this._cacheOffsetX+this._filterOffsetX, this._cacheOffsetY+this._filterOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale);
    return true;
  };
  
  /**
   * Applies this display object's transformation, alpha, globalCompositeOperation, clipping path (mask), and shadow
   * to the specified context. This is typically called prior to {{#crossLink "DisplayObject/draw"}}{{/crossLink}}.
   * @method updateContext
   * @param {CanvasRenderingContext2D} ctx The canvas 2D to update.
   **/
  p.updateContext = function(ctx) {
    var o=this, mask=o.mask, mtx= o._props.matrix;
    
    if (mask && mask.graphics && !mask.graphics.isEmpty()) {
      mask.getMatrix(mtx);
      ctx.transform(mtx.a,  mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty);
      
      mask.graphics.drawAsPath(ctx);
      ctx.clip();
      
      mtx.invert();
      ctx.transform(mtx.a,  mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty);
    }
    
    this.getMatrix(mtx);
    var tx = mtx.tx, ty = mtx.ty;
    if (DisplayObject._snapToPixelEnabled && o.snapToPixel) {
      tx = tx + (tx < 0 ? -0.5 : 0.5) | 0;
      ty = ty + (ty < 0 ? -0.5 : 0.5) | 0;
    }
    ctx.transform(mtx.a,  mtx.b, mtx.c, mtx.d, tx, ty);
    ctx.globalAlpha *= o.alpha;
    if (o.compositeOperation) { ctx.globalCompositeOperation = o.compositeOperation; }
    if (o.shadow) { this._applyShadow(ctx, o.shadow); }
  };

  /**
   * Draws the display object into a new canvas, which is then used for subsequent draws. For complex content
   * that does not change frequently (ex. a Container with many children that do not move, or a complex vector Shape),
   * this can provide for much faster rendering because the content does not need to be re-rendered each tick. The
   * cached display object can be moved, rotated, faded, etc freely, however if its content changes, you must
   * manually update the cache by calling <code>updateCache()</code> or <code>cache()</code> again. You must specify
   * the cache area via the x, y, w, and h parameters. This defines the rectangle that will be rendered and cached
   * using this display object's coordinates.
   *
   * <h4>Example</h4>
   * For example if you defined a Shape that drew a circle at 0, 0 with a radius of 25:
   *
   *      var shape = new createjs.Shape();
   *      shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25);
   *      myShape.cache(-25, -25, 50, 50);
   *
   * Note that filters need to be defined <em>before</em> the cache is applied. Check out the {{#crossLink "Filter"}}{{/crossLink}}
   * class for more information. Some filters (ex. BlurFilter) will not work as expected in conjunction with the scale param.
   * 
   * Usually, the resulting cacheCanvas will have the dimensions width*scale by height*scale, however some filters (ex. BlurFilter)
   * will add padding to the canvas dimensions.
   *
   * @method cache
   * @param {Number} x The x coordinate origin for the cache region.
   * @param {Number} y The y coordinate origin for the cache region.
   * @param {Number} width The width of the cache region.
   * @param {Number} height The height of the cache region.
   * @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape using
   *  myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and rotate
   *  cached elements with greater fidelity. Default is 1.
   **/
  p.cache = function(x, y, width, height, scale) {
    // draw to canvas.
    scale = scale||1;
    if (!this.cacheCanvas) { this.cacheCanvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); }
    this._cacheWidth = width;
    this._cacheHeight = height;
    this._cacheOffsetX = x;
    this._cacheOffsetY = y;
    this._cacheScale = scale;
    this.updateCache();
  };

  /**
   * Redraws the display object to its cache. Calling updateCache without an active cache will throw an error.
   * If compositeOperation is null the current cache will be cleared prior to drawing. Otherwise the display object
   * will be drawn over the existing cache using the specified compositeOperation.
   *
   * <h4>Example</h4>
   * Clear the current graphics of a cached shape, draw some new instructions, and then update the cache. The new line
   * will be drawn on top of the old one.
   *
   *      // Not shown: Creating the shape, and caching it.
   *      shapeInstance.clear();
   *      shapeInstance.setStrokeStyle(3).beginStroke("#ff0000").moveTo(100, 100).lineTo(200,200);
   *      shapeInstance.updateCache();
   *
   * @method updateCache
   * @param {String} compositeOperation The compositeOperation to use, or null to clear the cache and redraw it.
   * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing">
   * whatwg spec on compositing</a>.
   **/
  p.updateCache = function(compositeOperation) {
    var cacheCanvas = this.cacheCanvas;
    if (!cacheCanvas) { throw "cache() must be called before updateCache()"; }
    var scale = this._cacheScale, offX = this._cacheOffsetX*scale, offY = this._cacheOffsetY*scale;
    var w = this._cacheWidth, h = this._cacheHeight, ctx = cacheCanvas.getContext("2d");
    
    var fBounds = this._getFilterBounds();
    offX += (this._filterOffsetX = fBounds.x);
    offY += (this._filterOffsetY = fBounds.y);
    
    w = Math.ceil(w*scale) + fBounds.width;
    h = Math.ceil(h*scale) + fBounds.height;
    if (w != cacheCanvas.width || h != cacheCanvas.height) {
      // TODO: it would be nice to preserve the content if there is a compositeOperation.
      cacheCanvas.width = w;
      cacheCanvas.height = h;
    } else if (!compositeOperation) {
      ctx.clearRect(0, 0, w+1, h+1);
    }
    
    ctx.save();
    ctx.globalCompositeOperation = compositeOperation;
    ctx.setTransform(scale, 0, 0, scale, -offX, -offY);
    this.draw(ctx, true);
    // TODO: filters and cache scale don't play well together at present.
    this._applyFilters();
    ctx.restore();
    this.cacheID = DisplayObject._nextCacheID++;
  };

  /**
   * Clears the current cache. See {{#crossLink "DisplayObject/cache"}}{{/crossLink}} for more information.
   * @method uncache
   **/
  p.uncache = function() {
    this._cacheDataURL = this.cacheCanvas = null;
    this.cacheID = this._cacheOffsetX = this._cacheOffsetY = this._filterOffsetX = this._filterOffsetY = 0;
    this._cacheScale = 1;
  };
  
  /**
   * Returns a data URL for the cache, or null if this display object is not cached.
   * Uses cacheID to ensure a new data URL is not generated if the cache has not changed.
   * @method getCacheDataURL
   * @return {String} The image data url for the cache.
   **/
  p.getCacheDataURL = function() {
    if (!this.cacheCanvas) { return null; }
    if (this.cacheID != this._cacheDataURLID) { this._cacheDataURL = this.cacheCanvas.toDataURL(); }
    return this._cacheDataURL;
  };

  /**
   * Transforms the specified x and y position from the coordinate space of the display object
   * to the global (stage) coordinate space. For example, this could be used to position an HTML label
   * over a specific point on a nested display object. Returns a Point instance with x and y properties
   * correlating to the transformed coordinates on the stage.
   *
   * <h4>Example</h4>
   *
   *      displayObject.x = 300;
   *      displayObject.y = 200;
   *      stage.addChild(displayObject);
   *      var point = myDisplayObject.localToGlobal(100, 100);
   *      // Results in x=400, y=300
   *
   * @method localToGlobal
   * @param {Number} x The x position in the source display object to transform.
   * @param {Number} y The y position in the source display object to transform.
   * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 
   * @return {Point} A Point instance with x and y properties correlating to the transformed coordinates
   * on the stage.
   **/
  p.localToGlobal = function(x, y, pt) {
    return this.getConcatenatedMatrix(this._props.matrix).transformPoint(x,y, pt||new createjs.Point());
  };

  /**
   * Transforms the specified x and y position from the global (stage) coordinate space to the
   * coordinate space of the display object. For example, this could be used to determine
   * the current mouse position within the display object. Returns a Point instance with x and y properties
   * correlating to the transformed position in the display object's coordinate space.
   *
   * <h4>Example</h4>
   *
   *      displayObject.x = 300;
   *      displayObject.y = 200;
   *      stage.addChild(displayObject);
   *      var point = myDisplayObject.globalToLocal(100, 100);
   *      // Results in x=-200, y=-100
   *
   * @method globalToLocal
   * @param {Number} x The x position on the stage to transform.
   * @param {Number} y The y position on the stage to transform.
   * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 
   * @return {Point} A Point instance with x and y properties correlating to the transformed position in the
   * display object's coordinate space.
   **/
  p.globalToLocal = function(x, y, pt) {
    return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(x,y, pt||new createjs.Point());
  };

  /**
   * Transforms the specified x and y position from the coordinate space of this display object to the coordinate
   * space of the target display object. Returns a Point instance with x and y properties correlating to the
   * transformed position in the target's coordinate space. Effectively the same as using the following code with
   * {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}.
   *
   *      var pt = this.localToGlobal(x, y);
   *      pt = target.globalToLocal(pt.x, pt.y);
   *
   * @method localToLocal
   * @param {Number} x The x position in the source display object to transform.
   * @param {Number} y The y position on the source display object to transform.
   * @param {DisplayObject} target The target display object to which the coordinates will be transformed.
   * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 
   * @return {Point} Returns a Point instance with x and y properties correlating to the transformed position
   * in the target's coordinate space.
   **/
  p.localToLocal = function(x, y, target, pt) {
    pt = this.localToGlobal(x, y, pt);
    return target.globalToLocal(pt.x, pt.y, pt);
  };

  /**
   * Shortcut method to quickly set the transform properties on the display object. All parameters are optional.
   * Omitted parameters will have the default value set.
   *
   * <h4>Example</h4>
   *
   *      displayObject.setTransform(100, 100, 2, 2);
   *
   * @method setTransform
   * @param {Number} [x=0] The horizontal translation (x position) in pixels
   * @param {Number} [y=0] The vertical translation (y position) in pixels
   * @param {Number} [scaleX=1] The horizontal scale, as a percentage of 1
   * @param {Number} [scaleY=1] the vertical scale, as a percentage of 1
   * @param {Number} [rotation=0] The rotation, in degrees
   * @param {Number} [skewX=0] The horizontal skew factor
   * @param {Number} [skewY=0] The vertical skew factor
   * @param {Number} [regX=0] The horizontal registration point in pixels
   * @param {Number} [regY=0] The vertical registration point in pixels
   * @return {DisplayObject} Returns this instance. Useful for chaining commands.
   * @chainable
  */
  p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
    this.x = x || 0;
    this.y = y || 0;
    this.scaleX = scaleX == null ? 1 : scaleX;
    this.scaleY = scaleY == null ? 1 : scaleY;
    this.rotation = rotation || 0;
    this.skewX = skewX || 0;
    this.skewY = skewY || 0;
    this.regX = regX || 0;
    this.regY = regY || 0;
    return this;
  };
  
  /**
   * Returns a matrix based on this object's current transform.
   * @method getMatrix
   * @param {Matrix2D} matrix Optional. A Matrix2D object to populate with the calculated values. If null, a new
   * Matrix object is returned.
   * @return {Matrix2D} A matrix representing this display object's transform.
   **/
  p.getMatrix = function(matrix) {
    var o = this, mtx = matrix&&matrix.identity() || new createjs.Matrix2D();
    return o.transformMatrix ?  mtx.copy(o.transformMatrix) : mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY);
  };
  
  /**
   * Generates a Matrix2D object representing the combined transform of the display object and all of its
   * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). This can
   * be used to transform positions between coordinate spaces, such as with {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}}
   * and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}.
   * @method getConcatenatedMatrix
   * @param {Matrix2D} [matrix] A {{#crossLink "Matrix2D"}}{{/crossLink}} object to populate with the calculated values.
   * If null, a new Matrix2D object is returned.
   * @return {Matrix2D} The combined matrix.
   **/
  p.getConcatenatedMatrix = function(matrix) {
    var o = this, mtx = this.getMatrix(matrix);
    while (o = o.parent) {
      mtx.prependMatrix(o.getMatrix(o._props.matrix));
    }
    return mtx;
  };
  
  /**
   * Generates a DisplayProps object representing the combined display properties of the  object and all of its
   * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}).
   * @method getConcatenatedDisplayProps
   * @param {DisplayProps} [props] A {{#crossLink "DisplayProps"}}{{/crossLink}} object to populate with the calculated values.
   * If null, a new DisplayProps object is returned.
   * @return {DisplayProps} The combined display properties.
   **/
  p.getConcatenatedDisplayProps = function(props) {
    props = props ? props.identity() : new createjs.DisplayProps();
    var o = this, mtx = o.getMatrix(props.matrix); 
    do {
      props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation);
      
      // we do this to avoid problems with the matrix being used for both operations when o._props.matrix is passed in as the props param.
      // this could be simplified (ie. just done as part of the prepend above) if we switched to using a pool.
      if (o != this) { mtx.prependMatrix(o.getMatrix(o._props.matrix)); }
    } while (o = o.parent);
    return props;
  };

  /**
   * Tests whether the display object intersects the specified point in local coordinates (ie. draws a pixel with alpha > 0 at
   * the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation of the display object.
   *
   * <h4>Example</h4>
   *
   *      stage.addEventListener("stagemousedown", handleMouseDown);
   *      function handleMouseDown(event) {
   *          var hit = myShape.hitTest(event.stageX, event.stageY);
   *      }
   *
   * Please note that shape-to-shape collision is not currently supported by EaselJS.
   * @method hitTest
   * @param {Number} x The x position to check in the display object's local coordinates.
   * @param {Number} y The y position to check in the display object's local coordinates.
   * @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject intersect the specified
   * local Point.
  */
  p.hitTest = function(x, y) {
    var ctx = DisplayObject._hitTestContext;
    ctx.setTransform(1, 0, 0, 1, -x, -y);
    this.draw(ctx);

    var hit = this._testHit(ctx);
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, 2, 2);
    return hit;
  };
  
  /**
   * Provides a chainable shortcut method for setting a number of properties on the instance.
   *
   * <h4>Example</h4>
   *
   *      var myGraphics = new createjs.Graphics().beginFill("#ff0000").drawCircle(0, 0, 25);
   *      var shape = stage.addChild(new Shape()).set({graphics:myGraphics, x:100, y:100, alpha:0.5});
   *
   * @method set
   * @param {Object} props A generic object containing properties to copy to the DisplayObject instance.
   * @return {DisplayObject} Returns the instance the method is called on (useful for chaining calls.)
   * @chainable
  */
  p.set = function(props) {
    for (var n in props) { this[n] = props[n]; }
    return this;
  };
  
  /**
   * Returns a rectangle representing this object's bounds in its local coordinate system (ie. with no transformation).
   * Objects that have been cached will return the bounds of the cache.
   * 
   * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use 
   * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container
   * bounds.
   * 
   * <table>
   *  <tr><td><b>All</b></td><td>
   *    All display objects support setting bounds manually using setBounds(). Likewise, display objects that
   *    have been cached using cache() will return the bounds of their cache. Manual and cache bounds will override
   *    the automatic calculations listed below.
   *  </td></tr>
   *  <tr><td><b>Bitmap</b></td><td>
   *    Returns the width and height of the sourceRect (if specified) or image, extending from (x=0,y=0).
   *  </td></tr>
   *  <tr><td><b>Sprite</b></td><td>
   *    Returns the bounds of the current frame. May have non-zero x/y if a frame registration point was specified
   *    in the spritesheet data. See also {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}}
   *  </td></tr>
   *  <tr><td><b>Container</b></td><td>
   *    Returns the aggregate (combined) bounds of all children that return a non-null value from getBounds().
   *  </td></tr>
   *  <tr><td><b>Shape</b></td><td>
   *    Does not currently support automatic bounds calculations. Use setBounds() to manually define bounds.
   *  </td></tr>
   *  <tr><td><b>Text</b></td><td>
   *    Returns approximate bounds. Horizontal values (x/width) are quite accurate, but vertical values (y/height) are
   *    not, especially when using textBaseline values other than "top".
   *  </td></tr>
   *  <tr><td><b>BitmapText</b></td><td>
   *    Returns approximate bounds. Values will be more accurate if spritesheet frame registration points are close
   *    to (x=0,y=0).
   *  </td></tr>
  * </table>
   * 
   * Bounds can be expensive to calculate for some objects (ex. text, or containers with many children), and
   * are recalculated each time you call getBounds(). You can prevent recalculation on static objects by setting the
   * bounds explicitly:
   * 
   *  var bounds = obj.getBounds();
   *  obj.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
   *  // getBounds will now use the set values, instead of recalculating
   * 
   * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its
   * values if you need to retain it.
   * 
   *  var myBounds = obj.getBounds().clone();
   *  // OR:
   *  myRect.copy(obj.getBounds());
   * 
   * @method getBounds
   * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this
   * object.
   **/
  p.getBounds = function() {
    if (this._bounds) { return this._rectangle.copy(this._bounds); }
    var cacheCanvas = this.cacheCanvas;
    if (cacheCanvas) {
      var scale = this._cacheScale;
      return this._rectangle.setValues(this._cacheOffsetX, this._cacheOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale);
    }
    return null;
  };
  
  /**
   * Returns a rectangle representing this object's bounds in its parent's coordinate system (ie. with transformations applied).
   * Objects that have been cached will return the transformed bounds of the cache.
   * 
   * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use 
   * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container
   * bounds.
   * 
   * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its
   * values if you need to retain it.
   * 
   * Container instances calculate aggregate bounds for all children that return bounds via getBounds.
   * @method getTransformedBounds
   * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this object.
   **/
  p.getTransformedBounds = function() {
    return this._getBounds();
  };
  
  /**
   * Allows you to manually specify the bounds of an object that either cannot calculate their own bounds (ex. Shape &
   * Text) for future reference, or so the object can be included in Container bounds. Manually set bounds will always
   * override calculated bounds.
   * 
   * The bounds should be specified in the object's local (untransformed) coordinates. For example, a Shape instance
   * with a 25px radius circle centered at 0,0 would have bounds of (-25, -25, 50, 50).
   * @method setBounds
   * @param {Number} x The x origin of the bounds. Pass null to remove the manual bounds.
   * @param {Number} y The y origin of the bounds.
   * @param {Number} width The width of the bounds.
   * @param {Number} height The height of the bounds.
   **/
  p.setBounds = function(x, y, width, height) {
    if (x == null) { this._bounds = x; }
    this._bounds = (this._bounds || new createjs.Rectangle()).setValues(x, y, width, height);
  };

  /**
   * Returns a clone of this DisplayObject. Some properties that are specific to this instance's current context are
   * reverted to their defaults (for example .parent). Caches are not maintained across clones, and some elements
   * are copied by reference (masks, individual filter instances, hit area)
   * @method clone
   * @return {DisplayObject} A clone of the current DisplayObject instance.
   **/
  p.clone = function() {
    return this._cloneProps(new DisplayObject());
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[DisplayObject (name="+  this.name +")]";
  };


// private methods:
  // separated so it can be used more easily in subclasses:
  /**
   * @method _cloneProps
   * @param {DisplayObject} o The DisplayObject instance which will have properties from the current DisplayObject
   * instance copied into.
   * @return {DisplayObject} o
   * @protected
   **/
  p._cloneProps = function(o) {
    o.alpha = this.alpha;
    o.mouseEnabled = this.mouseEnabled;
    o.tickEnabled = this.tickEnabled;
    o.name = this.name;
    o.regX = this.regX;
    o.regY = this.regY;
    o.rotation = this.rotation;
    o.scaleX = this.scaleX;
    o.scaleY = this.scaleY;
    o.shadow = this.shadow;
    o.skewX = this.skewX;
    o.skewY = this.skewY;
    o.visible = this.visible;
    o.x  = this.x;
    o.y = this.y;
    o.compositeOperation = this.compositeOperation;
    o.snapToPixel = this.snapToPixel;
    o.filters = this.filters==null?null:this.filters.slice(0);
    o.mask = this.mask;
    o.hitArea = this.hitArea;
    o.cursor = this.cursor;
    o._bounds = this._bounds;
    return o;
  };

  /**
   * @method _applyShadow
   * @protected
   * @param {CanvasRenderingContext2D} ctx
   * @param {Shadow} shadow
   **/
  p._applyShadow = function(ctx, shadow) {
    shadow = shadow || Shadow.identity;
    ctx.shadowColor = shadow.color;
    ctx.shadowOffsetX = shadow.offsetX;
    ctx.shadowOffsetY = shadow.offsetY;
    ctx.shadowBlur = shadow.blur;
  };
  
  
  /**
   * @method _tick
   * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs.
   * @protected
   **/
  p._tick = function(evtObj) {
    // because tick can be really performance sensitive, check for listeners before calling dispatchEvent.
    var ls = this._listeners;
    if (ls && ls["tick"]) {
      // reset & reuse the event object to avoid construction / GC costs:
      evtObj.target = null;
      evtObj.propagationStopped = evtObj.immediatePropagationStopped = false;
      this.dispatchEvent(evtObj);
    }
  };

  /**
   * @method _testHit
   * @protected
   * @param {CanvasRenderingContext2D} ctx
   * @return {Boolean}
   **/
  p._testHit = function(ctx) {
    try {
      var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1;
    } catch (e) {
      if (!DisplayObject.suppressCrossDomainErrors) {
        throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images.";
      }
    }
    return hit;
  };

  /**
   * @method _applyFilters
   * @protected
   **/
  p._applyFilters = function() {
    if (!this.filters || this.filters.length == 0 || !this.cacheCanvas) { return; }
    var l = this.filters.length;
    var ctx = this.cacheCanvas.getContext("2d");
    var w = this.cacheCanvas.width;
    var h = this.cacheCanvas.height;
    for (var i=0; i<l; i++) {
      this.filters[i].applyFilter(ctx, 0, 0, w, h);
    }
  };
  
  /**
   * @method _getFilterBounds
   * @return {Rectangle}
   * @protected
   **/
  p._getFilterBounds = function(rect) {
    var l, filters = this.filters, bounds = this._rectangle.setValues(0,0,0,0);
    if (!filters || !(l=filters.length)) { return bounds; }
    
    for (var i=0; i<l; i++) {
      var f = this.filters[i];
      f.getBounds&&f.getBounds(bounds);
    }
    return bounds;
  };
  
  /**
   * @method _getBounds
   * @param {Matrix2D} matrix
   * @param {Boolean} ignoreTransform If true, does not apply this object's transform.
   * @return {Rectangle}
   * @protected
   **/
  p._getBounds = function(matrix, ignoreTransform){
    return this._transformBounds(this.getBounds(), matrix, ignoreTransform);
  };
  
  /**
   * @method _transformBounds
   * @param {Rectangle} bounds
   * @param {Matrix2D} matrix
   * @param {Boolean} ignoreTransform
   * @return {Rectangle}
   * @protected
   **/
  p._transformBounds = function(bounds, matrix, ignoreTransform) {
    if (!bounds) { return bounds; }
    var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height, mtx = this._props.matrix;
    mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx);
    
    if (x || y) { mtx.appendTransform(0,0,1,1,0,0,0,-x,-y); } // TODO: simplify this.
    if (matrix) { mtx.prependMatrix(matrix); }
    
    var x_a = width*mtx.a, x_b = width*mtx.b;
    var y_c = height*mtx.c, y_d = height*mtx.d;
    var tx = mtx.tx, ty = mtx.ty;
    
    var minX = tx, maxX = tx, minY = ty, maxY = ty;

    if ((x = x_a + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; }
    if ((x = x_a + y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; }
    if ((x = y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; }
    
    if ((y = x_b + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; }
    if ((y = x_b + y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; }
    if ((y = y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; }
    
    return bounds.setValues(minX, minY, maxX-minX, maxY-minY);
  };
  
  /**
   * Indicates whether the display object has any mouse event listeners or a cursor.
   * @method _isMouseOpaque
   * @return {Boolean}
   * @protected
   **/
  p._hasMouseEventListener = function() {
    var evts = DisplayObject._MOUSE_EVENTS;
    for (var i= 0, l=evts.length; i<l; i++) {
      if (this.hasEventListener(evts[i])) { return true; }
    }
    return !!this.cursor;
  };

  createjs.DisplayObject = createjs.promote(DisplayObject, "EventDispatcher");
}());

//##############################################################################
// Container.js
//##############################################################################

(function() {
  "use strict";
  

// constructor:
/**
 * A Container is a nestable display list that allows you to work with compound display elements. For  example you could
 * group arm, leg, torso and head {{#crossLink "Bitmap"}}{{/crossLink}} instances together into a Person Container, and
 * transform them as a group, while still being able to move the individual parts relative to each other. Children of
 * containers have their <code>transform</code> and <code>alpha</code> properties concatenated with their parent
 * Container.
 *
 * For example, a {{#crossLink "Shape"}}{{/crossLink}} with x=100 and alpha=0.5, placed in a Container with <code>x=50</code>
 * and <code>alpha=0.7</code> will be rendered to the canvas at <code>x=150</code> and <code>alpha=0.35</code>.
 * Containers have some overhead, so you generally shouldn't create a Container to hold a single child.
 *
 * <h4>Example</h4>
 *
 *      var container = new createjs.Container();
 *      container.addChild(bitmapInstance, shapeInstance);
 *      container.x = 100;
 *
 * @class Container
 * @extends DisplayObject
 * @constructor
 **/
  function Container() {
    this.DisplayObject_constructor();
    
  // public properties:
    /**
     * The array of children in the display list. You should usually use the child management methods such as
     * {{#crossLink "Container/addChild"}}{{/crossLink}}, {{#crossLink "Container/removeChild"}}{{/crossLink}},
     * {{#crossLink "Container/swapChildren"}}{{/crossLink}}, etc, rather than accessing this directly, but it is
     * included for advanced uses.
     * @property children
     * @type Array
     * @default null
     **/
    this.children = [];
    
    /**
     * Indicates whether the children of this container are independently enabled for mouse/pointer interaction.
     * If false, the children will be aggregated under the container - for example, a click on a child shape would
     * trigger a click event on the container.
     * @property mouseChildren
     * @type Boolean
     * @default true
     **/
    this.mouseChildren = true;
    
    /**
     * If false, the tick will not be propagated to children of this Container. This can provide some performance benefits.
     * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates
     * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling).
     * @property tickChildren
     * @type Boolean
     * @default true
     **/
    this.tickChildren = true;
  }
  var p = createjs.extend(Container, createjs.DisplayObject);
  
  
// getter / setters:
  /**
   * Use the {{#crossLink "Container/numChildren:property"}}{{/crossLink}} property instead.
   * @method getNumChildren
   * @return {Number}
   * @deprecated
   **/
  p.getNumChildren = function() {
    return this.children.length;
  };

  /**
   * Returns the number of children in the container.
   * @property numChildren
   * @type {Number}
   * @readonly
   **/
  try {
    Object.defineProperties(p, {
      numChildren: { get: p.getNumChildren }
    });
  } catch (e) {}
  

// public methods:
  /**
   * Constructor alias for backwards compatibility. This method will be removed in future versions.
   * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
   * @method initialize
   * @deprecated in favour of `createjs.promote()`
   **/
  p.initialize = Container; // TODO: deprecated.
  
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var hasContent = this.cacheCanvas || this.children.length;
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache.
   * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
   * into itself).
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
    
    // this ensures we don't have issues with display list changes that occur during a draw:
    var list = this.children.slice();
    for (var i=0,l=list.length; i<l; i++) {
      var child = list[i];
      if (!child.isVisible()) { continue; }
      
      // draw the child:
      ctx.save();
      child.updateContext(ctx);
      child.draw(ctx);
      ctx.restore();
    }
    return true;
  };
  
  /**
   * Adds a child to the top of the display list.
   *
   * <h4>Example</h4>
   *
   *    container.addChild(bitmapInstance);
   *
   * You can also add multiple children at once:
   *
   *    container.addChild(bitmapInstance, shapeInstance, textInstance);
   *
   * @method addChild
   * @param {DisplayObject} child The display object to add.
   * @return {DisplayObject} The child that was added, or the last child if multiple children were added.
   **/
  p.addChild = function(child) {
    if (child == null) { return child; }
    var l = arguments.length;
    if (l > 1) {
      for (var i=0; i<l; i++) { this.addChild(arguments[i]); }
      return arguments[l-1];
    }
    if (child.parent) { child.parent.removeChild(child); }
    child.parent = this;
    this.children.push(child);
    child.dispatchEvent("added");
    return child;
  };

  /**
   * Adds a child to the display list at the specified index, bumping children at equal or greater indexes up one, and
   * setting its parent to this Container.
   *
   * <h4>Example</h4>
   *
   *      addChildAt(child1, index);
   *
   * You can also add multiple children, such as:
   *
   *      addChildAt(child1, child2, ..., index);
   *
   * The index must be between 0 and numChildren. For example, to add myShape under otherShape in the display list,
   * you could use:
   *
   *      container.addChildAt(myShape, container.getChildIndex(otherShape));
   *
   * This would also bump otherShape's index up by one. Fails silently if the index is out of range.
   *
   * @method addChildAt
   * @param {DisplayObject} child The display object to add.
   * @param {Number} index The index to add the child at.
   * @return {DisplayObject} Returns the last child that was added, or the last child if multiple children were added.
   **/
  p.addChildAt = function(child, index) {
    var l = arguments.length;
    var indx = arguments[l-1]; // can't use the same name as the index param or it replaces arguments[1]
    if (indx < 0 || indx > this.children.length) { return arguments[l-2]; }
    if (l > 2) {
      for (var i=0; i<l-1; i++) { this.addChildAt(arguments[i], indx+i); }
      return arguments[l-2];
    }
    if (child.parent) { child.parent.removeChild(child); }
    child.parent = this;
    this.children.splice(index, 0, child);
    child.dispatchEvent("added");
    return child;
  };

  /**
   * Removes the specified child from the display list. Note that it is faster to use removeChildAt() if the index is
   * already known.
   *
   * <h4>Example</h4>
   *
   *      container.removeChild(child);
   *
   * You can also remove multiple children:
   *
   *      removeChild(child1, child2, ...);
   *
   * Returns true if the child (or children) was removed, or false if it was not in the display list.
   * @method removeChild
   * @param {DisplayObject} child The child to remove.
   * @return {Boolean} true if the child (or children) was removed, or false if it was not in the display list.
   **/
  p.removeChild = function(child) {
    var l = arguments.length;
    if (l > 1) {
      var good = true;
      for (var i=0; i<l; i++) { good = good && this.removeChild(arguments[i]); }
      return good;
    }
    return this.removeChildAt(createjs.indexOf(this.children, child));
  };

  /**
   * Removes the child at the specified index from the display list, and sets its parent to null.
   *
   * <h4>Example</h4>
   *
   *      container.removeChildAt(2);
   *
   * You can also remove multiple children:
   *
   *      container.removeChild(2, 7, ...)
   *
   * Returns true if the child (or children) was removed, or false if any index was out of range.
   * @method removeChildAt
   * @param {Number} index The index of the child to remove.
   * @return {Boolean} true if the child (or children) was removed, or false if any index was out of range.
   **/
  p.removeChildAt = function(index) {
    var l = arguments.length;
    if (l > 1) {
      var a = [];
      for (var i=0; i<l; i++) { a[i] = arguments[i]; }
      a.sort(function(a, b) { return b-a; });
      var good = true;
      for (var i=0; i<l; i++) { good = good && this.removeChildAt(a[i]); }
      return good;
    }
    if (index < 0 || index > this.children.length-1) { return false; }
    var child = this.children[index];
    if (child) { child.parent = null; }
    this.children.splice(index, 1);
    child.dispatchEvent("removed");
    return true;
  };

  /**
   * Removes all children from the display list.
   *
   * <h4>Example</h4>
   *
   *  container.removeAllChildren();
   *
   * @method removeAllChildren
   **/
  p.removeAllChildren = function() {
    var kids = this.children;
    while (kids.length) { this.removeChildAt(0); }
  };

  /**
   * Returns the child at the specified index.
   *
   * <h4>Example</h4>
   *
   *      container.getChildAt(2);
   *
   * @method getChildAt
   * @param {Number} index The index of the child to return.
   * @return {DisplayObject} The child at the specified index. Returns null if there is no child at the index.
   **/
  p.getChildAt = function(index) {
    return this.children[index];
  };
  
  /**
   * Returns the child with the specified name.
   * @method getChildByName
   * @param {String} name The name of the child to return.
   * @return {DisplayObject} The child with the specified name.
   **/
  p.getChildByName = function(name) {
    var kids = this.children;
    for (var i=0,l=kids.length;i<l;i++) {
      if(kids[i].name == name) { return kids[i]; }
    }
    return null;
  };

  /**
   * Performs an array sort operation on the child list.
   *
   * <h4>Example: Display children with a higher y in front.</h4>
   * 
   *      var sortFunction = function(obj1, obj2, options) {
   *          if (obj1.y > obj2.y) { return 1; }
   *          if (obj1.y < obj2.y) { return -1; }
   *          return 0;
   *      }
   *      container.sortChildren(sortFunction);
   *
   * @method sortChildren
   * @param {Function} sortFunction the function to use to sort the child list. See JavaScript's <code>Array.sort</code>
   * documentation for details.
   **/
  p.sortChildren = function(sortFunction) {
    this.children.sort(sortFunction);
  };

  /**
   * Returns the index of the specified child in the display list, or -1 if it is not in the display list.
   *
   * <h4>Example</h4>
   *
   *      var index = container.getChildIndex(child);
   *
   * @method getChildIndex
   * @param {DisplayObject} child The child to return the index of.
   * @return {Number} The index of the specified child. -1 if the child is not found.
   **/
  p.getChildIndex = function(child) {
    return createjs.indexOf(this.children, child);
  };
  
  /**
   * Swaps the children at the specified indexes. Fails silently if either index is out of range.
   * @method swapChildrenAt
   * @param {Number} index1
   * @param {Number} index2
   **/
  p.swapChildrenAt = function(index1, index2) {
    var kids = this.children;
    var o1 = kids[index1];
    var o2 = kids[index2];
    if (!o1 || !o2) { return; }
    kids[index1] = o2;
    kids[index2] = o1;
  };
  
  /**
   * Swaps the specified children's depth in the display list. Fails silently if either child is not a child of this
   * Container.
   * @method swapChildren
   * @param {DisplayObject} child1
   * @param {DisplayObject} child2
   **/
  p.swapChildren = function(child1, child2) {
    var kids = this.children;
    var index1,index2;
    for (var i=0,l=kids.length;i<l;i++) {
      if (kids[i] == child1) { index1 = i; }
      if (kids[i] == child2) { index2 = i; }
      if (index1 != null && index2 != null) { break; }
    }
    if (i==l) { return; } // TODO: throw error?
    kids[index1] = child2;
    kids[index2] = child1;
  };
  
  /**
   * Changes the depth of the specified child. Fails silently if the child is not a child of this container, or the index is out of range.
   * @param {DisplayObject} child
   * @param {Number} index  
   * @method setChildIndex
   **/
  p.setChildIndex = function(child, index) {
    var kids = this.children, l=kids.length;
    if (child.parent != this || index < 0 || index >= l) { return; }
    for (var i=0;i<l;i++) {
      if (kids[i] == child) { break; }
    }
    if (i==l || i == index) { return; }
    kids.splice(i,1);
    kids.splice(index,0,child);
  };

  /**
   * Returns true if the specified display object either is this container or is a descendent (child, grandchild, etc)
   * of this container.
   * @method contains
   * @param {DisplayObject} child The DisplayObject to be checked.
   * @return {Boolean} true if the specified display object either is this container or is a descendent.
   **/
  p.contains = function(child) {
    while (child) {
      if (child == this) { return true; }
      child = child.parent;
    }
    return false;
  };

  /**
   * Tests whether the display object intersects the specified local point (ie. draws a pixel with alpha > 0 at the
   * specified position). This ignores the alpha, shadow and compositeOperation of the display object, and all
   * transform properties including regX/Y.
   * @method hitTest
   * @param {Number} x The x position to check in the display object's local coordinates.
   * @param {Number} y The y position to check in the display object's local coordinates.
   * @return {Boolean} A Boolean indicating whether there is a visible section of a DisplayObject that overlaps the specified
   * coordinates.
   **/
  p.hitTest = function(x, y) {
    // TODO: optimize to use the fast cache check where possible.
    return (this.getObjectUnderPoint(x, y) != null);
  };

  /**
   * Returns an array of all display objects under the specified coordinates that are in this container's display
   * list. This routine ignores any display objects with {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}}
   * set to `false`. The array will be sorted in order of visual depth, with the top-most display object at index 0.
   * This uses shape based hit detection, and can be an expensive operation to run, so it is best to use it carefully.
   * For example, if testing for objects under the mouse, test on tick (instead of on {{#crossLink "DisplayObject/mousemove:event"}}{{/crossLink}}),
   * and only if the mouse's position has changed.
   * 
   * <ul>
   *     <li>By default (mode=0) this method evaluates all display objects.</li>
   *     <li>By setting the `mode` parameter to `1`, the {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}}
   *    and {{#crossLink "mouseChildren:property"}}{{/crossLink}} properties will be respected.</li>
   *     <li>Setting the `mode` to `2` additionally excludes display objects that do not have active mouse event
   *      listeners or a {{#crossLink "DisplayObject:cursor:property"}}{{/crossLink}} property. That is, only objects
   *      that would normally intercept mouse interaction will be included. This can significantly improve performance
   *      in some cases by reducing the number of display objects that need to be tested.</li>
   * </li>
   * 
   * This method accounts for both {{#crossLink "DisplayObject/hitArea:property"}}{{/crossLink}} and {{#crossLink "DisplayObject/mask:property"}}{{/crossLink}}.
   * @method getObjectsUnderPoint
   * @param {Number} x The x position in the container to test.
   * @param {Number} y The y position in the container to test.
   * @param {Number} [mode=0] The mode to use to determine which display objects to include. 0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects.
   * @return {Array} An Array of DisplayObjects under the specified coordinates.
   **/
  p.getObjectsUnderPoint = function(x, y, mode) {
    var arr = [];
    var pt = this.localToGlobal(x, y);
    this._getObjectsUnderPoint(pt.x, pt.y, arr, mode>0, mode==1);
    return arr;
  };

  /**
   * Similar to {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}, but returns only the top-most display
   * object. This runs significantly faster than <code>getObjectsUnderPoint()</code>, but is still potentially an expensive
   * operation. See {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}} for more information.
   * @method getObjectUnderPoint
   * @param {Number} x The x position in the container to test.
   * @param {Number} y The y position in the container to test.
   * @param {Number} mode The mode to use to determine which display objects to include.  0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects.
   * @return {DisplayObject} The top-most display object under the specified coordinates.
   **/
  p.getObjectUnderPoint = function(x, y, mode) {
    var pt = this.localToGlobal(x, y);
    return this._getObjectsUnderPoint(pt.x, pt.y, null, mode>0, mode==1);
  };
  
  /**
   * Docced in superclass.
   */
  p.getBounds = function() {
    return this._getBounds(null, true);
  };
  
  
  /**
   * Docced in superclass.
   */
  p.getTransformedBounds = function() {
    return this._getBounds();
  };

  /**
   * Returns a clone of this Container. Some properties that are specific to this instance's current context are
   * reverted to their defaults (for example .parent).
   * @method clone
   * @param {Boolean} [recursive=false] If true, all of the descendants of this container will be cloned recursively. If false, the
   * properties of the container will be cloned, but the new instance will not have any children.
   * @return {Container} A clone of the current Container instance.
   **/
  p.clone = function(recursive) {
    var o = this._cloneProps(new Container());
    if (recursive) { this._cloneChildren(o); }
    return o;
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Container (name="+  this.name +")]";
  };


// private methods:
  /**
   * @method _tick
   * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs.
   * @protected
   **/
  p._tick = function(evtObj) {
    if (this.tickChildren) {
      for (var i=this.children.length-1; i>=0; i--) {
        var child = this.children[i];
        if (child.tickEnabled && child._tick) { child._tick(evtObj); }
      }
    }
    this.DisplayObject__tick(evtObj);
  };
  
  /**
   * Recursively clones all children of this container, and adds them to the target container.
   * @method cloneChildren
   * @protected
   * @param {Container} o The target container.
   **/
  p._cloneChildren = function(o) {
    if (o.children.length) { o.removeAllChildren(); }
    var arr = o.children;
    for (var i=0, l=this.children.length; i<l; i++) {
      var clone = this.children[i].clone(true);
      clone.parent = o;
      arr.push(clone);
    }
  };

  /**
   * @method _getObjectsUnderPoint
   * @param {Number} x
   * @param {Number} y
   * @param {Array} arr
   * @param {Boolean} mouse If true, it will respect mouse interaction properties like mouseEnabled, mouseChildren, and active listeners.
   * @param {Boolean} activeListener If true, there is an active mouse event listener on a parent object.
   * @param {Number} currentDepth Indicates the current depth of the search.
   * @return {DisplayObject}
   * @protected
   **/
  p._getObjectsUnderPoint = function(x, y, arr, mouse, activeListener, currentDepth) {
    currentDepth = currentDepth || 0;
    if (!currentDepth && !this._testMask(this, x, y)) { return null; }
    var mtx, ctx = createjs.DisplayObject._hitTestContext;
    activeListener = activeListener || (mouse&&this._hasMouseEventListener());

    // draw children one at a time, and check if we get a hit:
    var children = this.children, l = children.length;
    for (var i=l-1; i>=0; i--) {
      var child = children[i];
      var hitArea = child.hitArea;
      if (!child.visible || (!hitArea && !child.isVisible()) || (mouse && !child.mouseEnabled)) { continue; }
      if (!hitArea && !this._testMask(child, x, y)) { continue; }
      
      // if a child container has a hitArea then we only need to check its hitArea, so we can treat it as a normal DO:
      if (!hitArea && child instanceof Container) {
        var result = child._getObjectsUnderPoint(x, y, arr, mouse, activeListener, currentDepth+1);
        if (!arr && result) { return (mouse && !this.mouseChildren) ? this : result; }
      } else {
        if (mouse && !activeListener && !child._hasMouseEventListener()) { continue; }
        
        // TODO: can we pass displayProps forward, to avoid having to calculate this backwards every time? It's kind of a mixed bag. When we're only hunting for DOs with event listeners, it may not make sense.
        var props = child.getConcatenatedDisplayProps(child._props);
        mtx = props.matrix;
        
        if (hitArea) {
          mtx.appendMatrix(hitArea.getMatrix(hitArea._props.matrix));
          props.alpha = hitArea.alpha;
        }
        
        ctx.globalAlpha = props.alpha;
        ctx.setTransform(mtx.a,  mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y);
        (hitArea||child).draw(ctx);
        if (!this._testHit(ctx)) { continue; }
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        ctx.clearRect(0, 0, 2, 2);
        if (arr) { arr.push(child); }
        else { return (mouse && !this.mouseChildren) ? this : child; }
      }
    }
    return null;
  };
  
  /**
   * @method _testMask
   * @param {DisplayObject} target
   * @param {Number} x
   * @param {Number} y
   * @return {Boolean} Indicates whether the x/y is within the masked region.
   * @protected
   **/
  p._testMask = function(target, x, y) {
    var mask = target.mask;
    if (!mask || !mask.graphics || mask.graphics.isEmpty()) { return true; }
    
    var mtx = this._props.matrix, parent = target.parent;
    mtx = parent ? parent.getConcatenatedMatrix(mtx) : mtx.identity();
    mtx = mask.getMatrix(mask._props.matrix).prependMatrix(mtx);
    
    var ctx = createjs.DisplayObject._hitTestContext;
    ctx.setTransform(mtx.a,  mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y);
    
    // draw the mask as a solid fill:
    mask.graphics.drawAsPath(ctx);
    ctx.fillStyle = "#000";
    ctx.fill();
    
    if (!this._testHit(ctx)) { return false; }
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, 2, 2);
    
    return true;
  };
  
  /**
   * @method _getBounds
   * @param {Matrix2D} matrix
   * @param {Boolean} ignoreTransform If true, does not apply this object's transform.
   * @return {Rectangle}
   * @protected
   **/
  p._getBounds = function(matrix, ignoreTransform) {
    var bounds = this.DisplayObject_getBounds();
    if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); }
    
    var mtx = this._props.matrix;
    mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx);
    if (matrix) { mtx.prependMatrix(matrix); }
    
    var l = this.children.length, rect=null;
    for (var i=0; i<l; i++) {
      var child = this.children[i];
      if (!child.visible || !(bounds = child._getBounds(mtx))) { continue; }
      if (rect) { rect.extend(bounds.x, bounds.y, bounds.width, bounds.height); }
      else { rect = bounds.clone(); }
    }
    return rect;
  };


  createjs.Container = createjs.promote(Container, "DisplayObject");
}());

//##############################################################################
// Stage.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * A stage is the root level {{#crossLink "Container"}}{{/crossLink}} for a display list. Each time its {{#crossLink "Stage/tick"}}{{/crossLink}}
   * method is called, it will render its display list to its target canvas.
   *
   * <h4>Example</h4>
   * This example creates a stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child
   * and redraw the stage using {{#crossLink "Stage/update"}}{{/crossLink}}.
   *
   *      var stage = new createjs.Stage("canvasElementId");
   *      var image = new createjs.Bitmap("imagePath.png");
   *      stage.addChild(image);
   *      createjs.Ticker.addEventListener("tick", handleTick);
   *      function handleTick(event) {
   *          image.x += 10;
   *          stage.update();
   *      }
   *
   * @class Stage
   * @extends Container
   * @constructor
   * @param {HTMLCanvasElement | String | Object} canvas A canvas object that the Stage will render to, or the string id
   * of a canvas object in the current document.
   **/
  function Stage(canvas) {
    this.Container_constructor();
  
  
  // public properties:
    /**
     * Indicates whether the stage should automatically clear the canvas before each render. You can set this to <code>false</code>
     * to manually control clearing (for generative art, or when pointing multiple stages at the same canvas for
     * example).
     *
     * <h4>Example</h4>
     *
     *      var stage = new createjs.Stage("canvasId");
     *      stage.autoClear = false;
     *
     * @property autoClear
     * @type Boolean
     * @default true
     **/
    this.autoClear = true;
  
    /**
     * The canvas the stage will render to. Multiple stages can share a single canvas, but you must disable autoClear for all but the
     * first stage that will be ticked (or they will clear each other's render).
     *
     * When changing the canvas property you must disable the events on the old canvas, and enable events on the
     * new canvas or mouse events will not work as expected. For example:
     *
     *      myStage.enableDOMEvents(false);
     *      myStage.canvas = anotherCanvas;
     *      myStage.enableDOMEvents(true);
     *
     * @property canvas
     * @type HTMLCanvasElement | Object
     **/
    this.canvas = (typeof canvas == "string") ? document.getElementById(canvas) : canvas;
  
    /**
     * The current mouse X position on the canvas. If the mouse leaves the canvas, this will indicate the most recent
     * position over the canvas, and mouseInBounds will be set to false.
     * @property mouseX
     * @type Number
     * @readonly
     **/
    this.mouseX = 0;
  
    /**
     * The current mouse Y position on the canvas. If the mouse leaves the canvas, this will indicate the most recent
     * position over the canvas, and mouseInBounds will be set to false.
     * @property mouseY
     * @type Number
     * @readonly
     **/
    this.mouseY = 0;
  
    /**
     * Specifies the area of the stage to affect when calling update. This can be use to selectively
     * re-draw specific regions of the canvas. If null, the whole canvas area is drawn.
     * @property drawRect
     * @type {Rectangle}
     */
    this.drawRect = null;
  
    /**
     * Indicates whether display objects should be rendered on whole pixels. You can set the
     * {{#crossLink "DisplayObject/snapToPixel"}}{{/crossLink}} property of
     * display objects to false to enable/disable this behaviour on a per instance basis.
     * @property snapToPixelEnabled
     * @type Boolean
     * @default false
     **/
    this.snapToPixelEnabled = false;
  
    /**
     * Indicates whether the mouse is currently within the bounds of the canvas.
     * @property mouseInBounds
     * @type Boolean
     * @default false
     **/
    this.mouseInBounds = false;
  
    /**
     * If true, tick callbacks will be called on all display objects on the stage prior to rendering to the canvas.
     * @property tickOnUpdate
     * @type Boolean
     * @default true
     **/
    this.tickOnUpdate = true;
  
    /**
     * If true, mouse move events will continue to be called when the mouse leaves the target canvas. See
     * {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}}, and {{#crossLink "MouseEvent"}}{{/crossLink}}
     * x/y/rawX/rawY.
     * @property mouseMoveOutside
     * @type Boolean
     * @default false
     **/
    this.mouseMoveOutside = false;
    
    
    /**
     * Prevents selection of other elements in the html page if the user clicks and drags, or double clicks on the canvas.
     * This works by calling `preventDefault()` on any mousedown events (or touch equivalent) originating on the canvas.
     * @property preventSelection
     * @type Boolean
     * @default true
     **/
    this.preventSelection = true;
  
    /**
     * The hitArea property is not supported for Stage.
     * @property hitArea
     * @type {DisplayObject}
     * @default null
     */
     
     
  // private properties:
    /**
     * Holds objects with data for each active pointer id. Each object has the following properties:
     * x, y, event, target, overTarget, overX, overY, inBounds, posEvtObj (native event that last updated position)
     * @property _pointerData
     * @type {Object}
     * @private
     */
    this._pointerData = {};
  
    /**
     * Number of active pointers.
     * @property _pointerCount
     * @type {Object}
     * @private
     */
    this._pointerCount = 0;
  
    /**
     * The ID of the primary pointer.
     * @property _primaryPointerID
     * @type {Object}
     * @private
     */
    this._primaryPointerID = null;
  
    /**
     * @property _mouseOverIntervalID
     * @protected
     * @type Number
     **/
    this._mouseOverIntervalID = null;
    
    /**
     * @property _nextStage
     * @protected
     * @type Stage
     **/
    this._nextStage = null;
    
    /**
     * @property _prevStage
     * @protected
     * @type Stage
     **/
    this._prevStage = null;
    
    
  // initialize:
    this.enableDOMEvents(true);
  }
  var p = createjs.extend(Stage, createjs.Container);

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// events:
  /**
   * Dispatched when the user moves the mouse over the canvas.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event stagemousemove
   * @since 0.6.0
   */

  /**
   * Dispatched when the user presses their left mouse button on the canvas. See the {{#crossLink "MouseEvent"}}{{/crossLink}}
   * class for a listing of event properties.
   * @event stagemousedown
   * @since 0.6.0
   */

  /**
   * Dispatched when the user the user presses somewhere on the stage, then releases the mouse button anywhere that the page can detect it (this varies slightly between browsers).
   * You can use {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}} to check whether the mouse is currently within the stage bounds.
   * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
   * @event stagemouseup
   * @since 0.6.0
   */

  /**
   * Dispatched when the mouse moves from within the canvas area (mouseInBounds == true) to outside it (mouseInBounds == false).
   * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}}
   * class for a listing of event properties.
   * @event mouseleave
   * @since 0.7.0
   */

  /**
   * Dispatched when the mouse moves into the canvas area (mouseInBounds == false) from outside it (mouseInBounds == true).
   * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}}
   * class for a listing of event properties.
   * @event mouseenter
   * @since 0.7.0
   */
   
  /**
   * Dispatched each update immediately before the tick event is propagated through the display list.
   * You can call preventDefault on the event object to cancel propagating the tick event.
   * @event tickstart
   * @since 0.7.0
   */
   
  /**
   * Dispatched each update immediately after the tick event is propagated through the display list. Does not fire if
   * tickOnUpdate is false. Precedes the "drawstart" event.
   * @event tickend
   * @since 0.7.0
   */
   
  /**
   * Dispatched each update immediately before the canvas is cleared and the display list is drawn to it.
   * You can call preventDefault on the event object to cancel the draw.
   * @event drawstart
   * @since 0.7.0
   */
   
  /**
   * Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored.
   * @event drawend
   * @since 0.7.0
   */

   
// getter / setters:
  /**
   * Specifies a target stage that will have mouse / touch interactions relayed to it after this stage handles them.
   * This can be useful in cases where you have multiple layered canvases and want user interactions
   * events to pass through. For example, this would relay mouse events from topStage to bottomStage:
   *
   *      topStage.nextStage = bottomStage;
   *
   * To disable relaying, set nextStage to null.
   * 
   * MouseOver, MouseOut, RollOver, and RollOut interactions are also passed through using the mouse over settings
   * of the top-most stage, but are only processed if the target stage has mouse over interactions enabled.
   * Considerations when using roll over in relay targets:<OL>
   * <LI> The top-most (first) stage must have mouse over interactions enabled (via enableMouseOver)</LI>
   * <LI> All stages that wish to participate in mouse over interaction must enable them via enableMouseOver</LI>
   * <LI> All relay targets will share the frequency value of the top-most stage</LI>
   * </OL>
   * To illustrate, in this example the targetStage would process mouse over interactions at 10hz (despite passing
   * 30 as it's desired frequency):
   *  topStage.nextStage = targetStage;
   *  topStage.enableMouseOver(10);
   *  targetStage.enableMouseOver(30);
   * 
   * If the target stage's canvas is completely covered by this stage's canvas, you may also want to disable its
   * DOM events using:
   * 
   *  targetStage.enableDOMEvents(false);
   * 
   * @property nextStage
   * @type {Stage}
   **/
  p._get_nextStage = function() {
    return this._nextStage;
  };
  p._set_nextStage = function(value) {
    if (this._nextStage) { this._nextStage._prevStage = null; }
    if (value) { value._prevStage = this; }
    this._nextStage = value;
  };
  
  try {
    Object.defineProperties(p, {
      nextStage: { get: p._get_nextStage, set: p._set_nextStage }
    });
  } catch (e) {} // TODO: use Log


// public methods:
  /**
   * Each time the update method is called, the stage will call {{#crossLink "Stage/tick"}}{{/crossLink}}
   * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false,
   * and then render the display list to the canvas.
   *
   * @method update
   * @param {Object} [props] Props object to pass to `tick()`. Should usually be a {{#crossLink "Ticker"}}{{/crossLink}} event object, or similar object with a delta property.
   **/
  p.update = function(props) {
    if (!this.canvas) { return; }
    if (this.tickOnUpdate) { this.tick(props); }
    if (this.dispatchEvent("drawstart", false, true) === false) { return; }
    createjs.DisplayObject._snapToPixelEnabled = this.snapToPixelEnabled;
    var r = this.drawRect, ctx = this.canvas.getContext("2d");
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    if (this.autoClear) {
      if (r) { ctx.clearRect(r.x, r.y, r.width, r.height); }
      else { ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); }
    }
    ctx.save();
    if (this.drawRect) {
      ctx.beginPath();
      ctx.rect(r.x, r.y, r.width, r.height);
      ctx.clip();
    }
    this.updateContext(ctx);
    this.draw(ctx, false);
    ctx.restore();
    this.dispatchEvent("drawend");
  };
  
  /**
   * Propagates a tick event through the display list. This is automatically called by {{#crossLink "Stage/update"}}{{/crossLink}}
   * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false.
   *
   * If a props object is passed to `tick()`, then all of its properties will be copied to the event object that is
   * propagated to listeners.
   *
   * Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that
   * a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or equivalent object with a delta property) be
   * passed as the `props` parameter to `tick()`. For example:
   *
   *  Ticker.on("tick", handleTick);
   *  function handleTick(evtObj) {
   *    // clone the event object from Ticker, and add some custom data to it:
   *    var evt = evtObj.clone().set({greeting:"hello", name:"world"});
   *    
   *    // pass it to stage.update():
   *    myStage.update(evt); // subsequently calls tick() with the same param
   *  }
   *  
   *  // ...
   *  myDisplayObject.on("tick", handleDisplayObjectTick);
   *  function handleDisplayObjectTick(evt) {
   *    console.log(evt.delta); // the delta property from the Ticker tick event object
   *    console.log(evt.greeting, evt.name); // custom data: "hello world"
   *  }
   * 
   * @method tick
   * @param {Object} [props] An object with properties that should be copied to the event object. Should usually be a Ticker event object, or similar object with a delta property.
   **/
  p.tick = function(props) {
    if (!this.tickEnabled || this.dispatchEvent("tickstart", false, true) === false) { return; }
    var evtObj = new createjs.Event("tick");
    if (props) {
      for (var n in props) {
        if (props.hasOwnProperty(n)) { evtObj[n] = props[n]; }
      }
    }
    this._tick(evtObj);
    this.dispatchEvent("tickend");
  };

  /**
   * Default event handler that calls the Stage {{#crossLink "Stage/update"}}{{/crossLink}} method when a {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}}
   * event is received. This allows you to register a Stage instance as a event listener on {{#crossLink "Ticker"}}{{/crossLink}}
   * directly, using:
   *
   *      Ticker.addEventListener("tick", myStage");
   *
   * Note that if you subscribe to ticks using this pattern, then the tick event object will be passed through to
   * display object tick handlers, instead of <code>delta</code> and <code>paused</code> parameters.
   * @property handleEvent
   * @type Function
   **/
  p.handleEvent = function(evt) {
    if (evt.type == "tick") { this.update(evt); }
  };

  /**
   * Clears the target canvas. Useful if {{#crossLink "Stage/autoClear:property"}}{{/crossLink}} is set to `false`.
   * @method clear
   **/
  p.clear = function() {
    if (!this.canvas) { return; }
    var ctx = this.canvas.getContext("2d");
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1);
  };

  /**
   * Returns a data url that contains a Base64-encoded image of the contents of the stage. The returned data url can
   * be specified as the src value of an image element.
   * @method toDataURL
   * @param {String} [backgroundColor] The background color to be used for the generated image. Any valid CSS color
   * value is allowed. The default value is a transparent background.
   * @param {String} [mimeType="image/png"] The MIME type of the image format to be create. The default is "image/png". If an unknown MIME type
   * is passed in, or if the browser does not support the specified MIME type, the default value will be used.
   * @return {String} a Base64 encoded image.
   **/
  p.toDataURL = function(backgroundColor, mimeType) {
    var data, ctx = this.canvas.getContext('2d'), w = this.canvas.width, h = this.canvas.height;

    if (backgroundColor) {
      data = ctx.getImageData(0, 0, w, h);
      var compositeOperation = ctx.globalCompositeOperation;
      ctx.globalCompositeOperation = "destination-over";
      
      ctx.fillStyle = backgroundColor;
      ctx.fillRect(0, 0, w, h);
    }

    var dataURL = this.canvas.toDataURL(mimeType||"image/png");

    if(backgroundColor) {
      ctx.putImageData(data, 0, 0);
      ctx.globalCompositeOperation = compositeOperation;
    }

    return dataURL;
  };

  /**
   * Enables or disables (by passing a frequency of 0) mouse over ({{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}
   * and {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}) and roll over events ({{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}
   * and {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}) for this stage's display list. These events can
   * be expensive to generate, so they are disabled by default. The frequency of the events can be controlled
   * independently of mouse move events via the optional `frequency` parameter.
   *
   * <h4>Example</h4>
   *
   *      var stage = new createjs.Stage("canvasId");
   *      stage.enableMouseOver(10); // 10 updates per second
   *
   * @method enableMouseOver
   * @param {Number} [frequency=20] Optional param specifying the maximum number of times per second to broadcast
   * mouse over/out events. Set to 0 to disable mouse over events completely. Maximum is 50. A lower frequency is less
   * responsive, but uses less CPU.
   **/
  p.enableMouseOver = function(frequency) {
    if (this._mouseOverIntervalID) {
      clearInterval(this._mouseOverIntervalID);
      this._mouseOverIntervalID = null;
      if (frequency == 0) {
        this._testMouseOver(true);
      }
    }
    if (frequency == null) { frequency = 20; }
    else if (frequency <= 0) { return; }
    var o = this;
    this._mouseOverIntervalID = setInterval(function(){ o._testMouseOver(); }, 1000/Math.min(50,frequency));
  };

  /**
   * Enables or disables the event listeners that stage adds to DOM elements (window, document and canvas). It is good
   * practice to disable events when disposing of a Stage instance, otherwise the stage will continue to receive
   * events from the page.
   *
   * When changing the canvas property you must disable the events on the old canvas, and enable events on the
   * new canvas or mouse events will not work as expected. For example:
   *
   *      myStage.enableDOMEvents(false);
   *      myStage.canvas = anotherCanvas;
   *      myStage.enableDOMEvents(true);
   *
   * @method enableDOMEvents
   * @param {Boolean} [enable=true] Indicates whether to enable or disable the events. Default is true.
   **/
  p.enableDOMEvents = function(enable) {
    if (enable == null) { enable = true; }
    var n, o, ls = this._eventListeners;
    if (!enable && ls) {
      for (n in ls) {
        o = ls[n];
        o.t.removeEventListener(n, o.f, false);
      }
      this._eventListeners = null;
    } else if (enable && !ls && this.canvas) {
      var t = window.addEventListener ? window : document;
      var _this = this;
      ls = this._eventListeners = {};
      ls["mouseup"] = {t:t, f:function(e) { _this._handleMouseUp(e)} };
      ls["mousemove"] = {t:t, f:function(e) { _this._handleMouseMove(e)} };
      ls["dblclick"] = {t:this.canvas, f:function(e) { _this._handleDoubleClick(e)} };
      ls["mousedown"] = {t:this.canvas, f:function(e) { _this._handleMouseDown(e)} };

      for (n in ls) {
        o = ls[n];
        o.t.addEventListener(n, o.f, false);
      }
    }
  };

  /**
   * Stage instances cannot be cloned.
   * @method clone
   **/
  p.clone = function() {
    throw("Stage cannot be cloned.");
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Stage (name="+  this.name +")]";
  };


// private methods:
  /**
   * @method _getElementRect
   * @protected
   * @param {HTMLElement} e
   **/
  p._getElementRect = function(e) {
    var bounds;
    try { bounds = e.getBoundingClientRect(); } // this can fail on disconnected DOM elements in IE9
    catch (err) { bounds = {top: e.offsetTop, left: e.offsetLeft, width:e.offsetWidth, height:e.offsetHeight}; }

    var offX = (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || document.body.clientLeft || 0);
    var offY = (window.pageYOffset || document.scrollTop || 0) - (document.clientTop  || document.body.clientTop  || 0);

    var styles = window.getComputedStyle ? getComputedStyle(e,null) : e.currentStyle; // IE <9 compatibility.
    var padL = parseInt(styles.paddingLeft)+parseInt(styles.borderLeftWidth);
    var padT = parseInt(styles.paddingTop)+parseInt(styles.borderTopWidth);
    var padR = parseInt(styles.paddingRight)+parseInt(styles.borderRightWidth);
    var padB = parseInt(styles.paddingBottom)+parseInt(styles.borderBottomWidth);

    // note: in some browsers bounds properties are read only.
    return {
      left: bounds.left+offX+padL,
      right: bounds.right+offX-padR,
      top: bounds.top+offY+padT,
      bottom: bounds.bottom+offY-padB
    }
  };

  /**
   * @method _getPointerData
   * @protected
   * @param {Number} id
   **/
  p._getPointerData = function(id) {
    var data = this._pointerData[id];
    if (!data) { data = this._pointerData[id] = {x:0,y:0}; }
    return data;
  };

  /**
   * @method _handleMouseMove
   * @protected
   * @param {MouseEvent} e
   **/
  p._handleMouseMove = function(e) {
    if(!e){ e = window.event; }
    this._handlePointerMove(-1, e, e.pageX, e.pageY);
  };

  /**
   * @method _handlePointerMove
   * @protected
   * @param {Number} id
   * @param {Event} e
   * @param {Number} pageX
   * @param {Number} pageY
   * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
   **/
  p._handlePointerMove = function(id, e, pageX, pageY, owner) {
    if (this._prevStage && owner === undefined) { return; } // redundant listener.
    if (!this.canvas) { return; }
    var nextStage=this._nextStage, o=this._getPointerData(id);

    var inBounds = o.inBounds;
    this._updatePointerPosition(id, e, pageX, pageY);
    if (inBounds || o.inBounds || this.mouseMoveOutside) {
      if (id === -1 && o.inBounds == !inBounds) {
        this._dispatchMouseEvent(this, (inBounds ? "mouseleave" : "mouseenter"), false, id, o, e);
      }
      
      this._dispatchMouseEvent(this, "stagemousemove", false, id, o, e);
      this._dispatchMouseEvent(o.target, "pressmove", true, id, o, e);
    }
    
    nextStage&&nextStage._handlePointerMove(id, e, pageX, pageY, null);
  };

  /**
   * @method _updatePointerPosition
   * @protected
   * @param {Number} id
   * @param {Event} e
   * @param {Number} pageX
   * @param {Number} pageY
   **/
  p._updatePointerPosition = function(id, e, pageX, pageY) {
    var rect = this._getElementRect(this.canvas);
    pageX -= rect.left;
    pageY -= rect.top;

    var w = this.canvas.width;
    var h = this.canvas.height;
    pageX /= (rect.right-rect.left)/w;
    pageY /= (rect.bottom-rect.top)/h;
    var o = this._getPointerData(id);
    if (o.inBounds = (pageX >= 0 && pageY >= 0 && pageX <= w-1 && pageY <= h-1)) {
      o.x = pageX;
      o.y = pageY;
    } else if (this.mouseMoveOutside) {
      o.x = pageX < 0 ? 0 : (pageX > w-1 ? w-1 : pageX);
      o.y = pageY < 0 ? 0 : (pageY > h-1 ? h-1 : pageY);
    }

    o.posEvtObj = e;
    o.rawX = pageX;
    o.rawY = pageY;

    if (id === this._primaryPointerID || id === -1) {
      this.mouseX = o.x;
      this.mouseY = o.y;
      this.mouseInBounds = o.inBounds;
    }
  };

  /**
   * @method _handleMouseUp
   * @protected
   * @param {MouseEvent} e
   **/
  p._handleMouseUp = function(e) {
    this._handlePointerUp(-1, e, false);
  };

  /**
   * @method _handlePointerUp
   * @protected
   * @param {Number} id
   * @param {Event} e
   * @param {Boolean} clear
   * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
   **/
  p._handlePointerUp = function(id, e, clear, owner) {
    var nextStage = this._nextStage, o = this._getPointerData(id);
    if (this._prevStage && owner === undefined) { return; } // redundant listener.
    
    var target=null, oTarget = o.target;
    if (!owner && (oTarget || nextStage)) { target = this._getObjectsUnderPoint(o.x, o.y, null, true); }
    
    if (o.down) { this._dispatchMouseEvent(this, "stagemouseup", false, id, o, e, target); o.down = false; }
    
    if (target == oTarget) { this._dispatchMouseEvent(oTarget, "click", true, id, o, e); }
    this._dispatchMouseEvent(oTarget, "pressup", true, id, o, e);
    
    if (clear) {
      if (id==this._primaryPointerID) { this._primaryPointerID = null; }
      delete(this._pointerData[id]);
    } else { o.target = null; }
    
    nextStage&&nextStage._handlePointerUp(id, e, clear, owner || target && this);
  };

  /**
   * @method _handleMouseDown
   * @protected
   * @param {MouseEvent} e
   **/
  p._handleMouseDown = function(e) {
    this._handlePointerDown(-1, e, e.pageX, e.pageY);
  };

  /**
   * @method _handlePointerDown
   * @protected
   * @param {Number} id
   * @param {Event} e
   * @param {Number} pageX
   * @param {Number} pageY
   * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
   **/
  p._handlePointerDown = function(id, e, pageX, pageY, owner) {
    if (this.preventSelection) { e.preventDefault(); }
    if (this._primaryPointerID == null || id === -1) { this._primaryPointerID = id; } // mouse always takes over.
    
    if (pageY != null) { this._updatePointerPosition(id, e, pageX, pageY); }
    var target = null, nextStage = this._nextStage, o = this._getPointerData(id);
    if (!owner) { target = o.target = this._getObjectsUnderPoint(o.x, o.y, null, true); }

    if (o.inBounds) { this._dispatchMouseEvent(this, "stagemousedown", false, id, o, e, target); o.down = true; }
    this._dispatchMouseEvent(target, "mousedown", true, id, o, e);
    
    nextStage&&nextStage._handlePointerDown(id, e, pageX, pageY, owner || target && this);
  };

  /**
   * @method _testMouseOver
   * @param {Boolean} clear If true, clears the mouseover / rollover (ie. no target)
   * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
   * @param {Stage} eventTarget The stage that the cursor is actively over.
   * @protected
   **/
  p._testMouseOver = function(clear, owner, eventTarget) {
    if (this._prevStage && owner === undefined) { return; } // redundant listener.
    
    var nextStage = this._nextStage;
    if (!this._mouseOverIntervalID) {
      // not enabled for mouseover, but should still relay the event.
      nextStage&&nextStage._testMouseOver(clear, owner, eventTarget);
      return;
    }
    var o = this._getPointerData(-1);
    // only update if the mouse position has changed. This provides a lot of optimization, but has some trade-offs.
    if (!o || (!clear && this.mouseX == this._mouseOverX && this.mouseY == this._mouseOverY && this.mouseInBounds)) { return; }
    
    var e = o.posEvtObj;
    var isEventTarget = eventTarget || e&&(e.target == this.canvas);
    var target=null, common = -1, cursor="", t, i, l;
    
    if (!owner && (clear || this.mouseInBounds && isEventTarget)) {
      target = this._getObjectsUnderPoint(this.mouseX, this.mouseY, null, true);
      this._mouseOverX = this.mouseX;
      this._mouseOverY = this.mouseY;
    }

    var oldList = this._mouseOverTarget||[];
    var oldTarget = oldList[oldList.length-1];
    var list = this._mouseOverTarget = [];

    // generate ancestor list and check for cursor:
    t = target;
    while (t) {
      list.unshift(t);
      if (!cursor) { cursor = t.cursor; }
      t = t.parent;
    }
    this.canvas.style.cursor = cursor;
    if (!owner && eventTarget) { eventTarget.canvas.style.cursor = cursor; }

    // find common ancestor:
    for (i=0,l=list.length; i<l; i++) {
      if (list[i] != oldList[i]) { break; }
      common = i;
    }

    if (oldTarget != target) {
      this._dispatchMouseEvent(oldTarget, "mouseout", true, -1, o, e, target);
    }

    for (i=oldList.length-1; i>common; i--) {
      this._dispatchMouseEvent(oldList[i], "rollout", false, -1, o, e, target);
    }

    for (i=list.length-1; i>common; i--) {
      this._dispatchMouseEvent(list[i], "rollover", false, -1, o, e, oldTarget);
    }

    if (oldTarget != target) {
      this._dispatchMouseEvent(target, "mouseover", true, -1, o, e, oldTarget);
    }
    
    nextStage&&nextStage._testMouseOver(clear, owner || target && this, eventTarget || isEventTarget && this);
  };

  /**
   * @method _handleDoubleClick
   * @protected
   * @param {MouseEvent} e
   * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
   **/
  p._handleDoubleClick = function(e, owner) {
    var target=null, nextStage=this._nextStage, o=this._getPointerData(-1);
    if (!owner) {
      target = this._getObjectsUnderPoint(o.x, o.y, null, true);
      this._dispatchMouseEvent(target, "dblclick", true, -1, o, e);
    }
    nextStage&&nextStage._handleDoubleClick(e, owner || target && this);
  };

  /**
   * @method _dispatchMouseEvent
   * @protected
   * @param {DisplayObject} target
   * @param {String} type
   * @param {Boolean} bubbles
   * @param {Number} pointerId
   * @param {Object} o
   * @param {MouseEvent} [nativeEvent]
   * @param {DisplayObject} [relatedTarget]
   **/
  p._dispatchMouseEvent = function(target, type, bubbles, pointerId, o, nativeEvent, relatedTarget) {
    // TODO: might be worth either reusing MouseEvent instances, or adding a willTrigger method to avoid GC.
    if (!target || (!bubbles && !target.hasEventListener(type))) { return; }
    /*
    // TODO: account for stage transformations?
    this._mtx = this.getConcatenatedMatrix(this._mtx).invert();
    var pt = this._mtx.transformPoint(o.x, o.y);
    var evt = new createjs.MouseEvent(type, bubbles, false, pt.x, pt.y, nativeEvent, pointerId, pointerId==this._primaryPointerID || pointerId==-1, o.rawX, o.rawY);
    */
    var evt = new createjs.MouseEvent(type, bubbles, false, o.x, o.y, nativeEvent, pointerId, pointerId === this._primaryPointerID || pointerId === -1, o.rawX, o.rawY, relatedTarget);
    target.dispatchEvent(evt);
  };


  createjs.Stage = createjs.promote(Stage, "Container");
}());

//##############################################################################
// Bitmap.js
//##############################################################################

(function() {
  
  /**
   * A Bitmap represents an Image, Canvas, or Video in the display list. A Bitmap can be instantiated using an existing
   * HTML element, or a string.
   *
   * <h4>Example</h4>
   *
   *      var bitmap = new createjs.Bitmap("imagePath.jpg");
   *
   * <strong>Notes:</strong>
   * <ol>
   *     <li>When a string path or image tag that is not yet loaded is used, the stage may need to be redrawn before it
   *      will be displayed.</li>
   *     <li>Bitmaps with an SVG source currently will not respect an alpha value other than 0 or 1. To get around this,
   *     the Bitmap can be cached.</li>
   *     <li>Bitmaps with an SVG source will taint the canvas with cross-origin data, which prevents interactivity. This
   *     happens in all browsers except recent Firefox builds.</li>
   *     <li>Images loaded cross-origin will throw cross-origin security errors when interacted with using a mouse, using
   *     methods such as `getObjectUnderPoint`, or using filters, or caching. You can get around this by setting
   *     `crossOrigin` flags on your images before passing them to EaselJS, eg: `img.crossOrigin="Anonymous";`</li>
   * </ol>
   *
   * @class Bitmap
   * @extends DisplayObject
   * @constructor
   * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String} imageOrUri The source object or URI to an image to
   * display. This can be either an Image, Canvas, or Video object, or a string URI to an image file to load and use.
   * If it is a URI, a new Image object will be constructed and assigned to the .image property.
   **/
  function Bitmap(imageOrUri) {
    this.DisplayObject_constructor();
    
    
  // public properties:
    /**
     * The image to render. This can be an Image, a Canvas, or a Video. Not all browsers (especially
     * mobile browsers) support drawing video to a canvas.
     * @property image
     * @type HTMLImageElement | HTMLCanvasElement | HTMLVideoElement
     **/
    if (typeof imageOrUri == "string") {
      this.image = document.createElement("img");
      this.image.src = imageOrUri;
    } else {
      this.image = imageOrUri;
    }
  
    /**
     * Specifies an area of the source image to draw. If omitted, the whole image will be drawn.
     * Note that video sources must have a width / height set to work correctly with `sourceRect`.
     * @property sourceRect
     * @type Rectangle
     * @default null
     */
    this.sourceRect = null;
  }
  var p = createjs.extend(Bitmap, createjs.DisplayObject);
  
  
// public methods:
  /**
   * Constructor alias for backwards compatibility. This method will be removed in future versions.
   * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
   * @method initialize
   * @deprecated in favour of `createjs.promote()`
   **/
  p.initialize = Bitmap; // TODO: deprecated.

  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var image = this.image;
    var hasContent = this.cacheCanvas || (image && (image.naturalWidth || image.getContext || image.readyState >= 2));
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   *
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache.
   * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
   * into itself).
   * @return {Boolean}
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache) || !this.image) { return true; }
    var img = this.image, rect = this.sourceRect;
    if (rect) {
      // some browsers choke on out of bound values, so we'll fix them:
      var x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 = y1 + rect.height, x = 0, y = 0, w = img.width, h = img.height;
      if (x1 < 0) { x -= x1; x1 = 0; }
      if (x2 > w) { x2 = w; }
      if (y1 < 0) { y -= y1; y1 = 0; }
      if (y2 > h) { y2 = h; }
      ctx.drawImage(img, x1, y1, x2-x1, y2-y1, x, y, x2-x1, y2-y1);
    } else {
      ctx.drawImage(img, 0, 0);
    }
    return true;
  };
  
  //Note, the doc sections below document using the specified APIs (from DisplayObject)  from
  //Bitmap. This is why they have no method implementations.
  
  /**
   * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
   * You should <b>not</b> cache Bitmap instances as it can degrade performance.
   *
   * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
   * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
   * method.
   * @method cache
   **/
  
  /**
   * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
   * You should <b>not</b> cache Bitmap instances as it can degrade performance.
   *
   * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
   * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
   * method.
   * @method updateCache
   **/
  
  /**
   * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
   * You should <b>not</b> cache Bitmap instances as it can degrade performance.
   *
   * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
   * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
   * method.
   * @method uncache
   **/

  /**
   * Docced in superclass.
   */
  p.getBounds = function() {
    var rect = this.DisplayObject_getBounds();
    if (rect) { return rect; }
    var image = this.image, o = this.sourceRect || image;
    var hasContent = (image && (image.naturalWidth || image.getContext || image.readyState >= 2));
    return hasContent ? this._rectangle.setValues(0, 0, o.width, o.height) : null;
  };
  
  /**
   * Returns a clone of the Bitmap instance.
   * @method clone
   * @return {Bitmap} a clone of the Bitmap instance.
   **/
  p.clone = function() {
    var o = new Bitmap(this.image);
    if (this.sourceRect) { o.sourceRect = this.sourceRect.clone(); }
    this._cloneProps(o);
    return o;
  };
  
  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Bitmap (name="+  this.name +")]";
  };

  
  createjs.Bitmap = createjs.promote(Bitmap, "DisplayObject");
}());

//##############################################################################
// Sprite.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Displays a frame or sequence of frames (ie. an animation) from a SpriteSheet instance. A sprite sheet is a series of
   * images (usually animation frames) combined into a single image. For example, an animation consisting of 8 100x100
   * images could be combined into a 400x200 sprite sheet (4 frames across by 2 high). You can display individual frames,
   * play frames as an animation, and even sequence animations together.
   *
   * See the {{#crossLink "SpriteSheet"}}{{/crossLink}} class for more information on setting up frames and animations.
   *
   * <h4>Example</h4>
   *
   *      var instance = new createjs.Sprite(spriteSheet);
   *      instance.gotoAndStop("frameName");
   *
   * Until {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} is called,
   * only the first defined frame defined in the sprite sheet will be displayed.
   *
   * @class Sprite
   * @extends DisplayObject
   * @constructor
   * @param {SpriteSheet} spriteSheet The SpriteSheet instance to play back. This includes the source image(s), frame
   * dimensions, and frame data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information.
   * @param {String|Number} [frameOrAnimation] The frame number or animation to play initially.
   **/
  function Sprite(spriteSheet, frameOrAnimation) {
    this.DisplayObject_constructor();
    
    
  // public properties:
    /**
     * The frame index that will be drawn when draw is called. Note that with some {{#crossLink "SpriteSheet"}}{{/crossLink}}
     * definitions, this will advance non-sequentially. This will always be an integer value.
     * @property currentFrame
     * @type {Number}
     * @default 0
     * @readonly
     **/
    this.currentFrame = 0;
  
    /**
     * Returns the name of the currently playing animation.
     * @property currentAnimation
     * @type {String}
     * @final
     * @readonly
     **/
    this.currentAnimation = null;
  
    /**
     * Prevents the animation from advancing each tick automatically. For example, you could create a sprite
     * sheet of icons, set paused to true, and display the appropriate icon by setting <code>currentFrame</code>.
     * @property paused
     * @type {Boolean}
     * @default false
     **/
    this.paused = true;
  
    /**
     * The SpriteSheet instance to play back. This includes the source image, frame dimensions, and frame
     * data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information.
     * @property spriteSheet
     * @type {SpriteSheet}
     * @readonly
     **/
    this.spriteSheet = spriteSheet;
  
    /**
     * Specifies the current frame index within the currently playing animation. When playing normally, this will increase
     * from 0 to n-1, where n is the number of frames in the current animation.
     *
     * This could be a non-integer value if
     * using time-based playback (see {{#crossLink "Sprite/framerate"}}{{/crossLink}}, or if the animation's speed is
     * not an integer.
     * @property currentAnimationFrame
     * @type {Number}
     * @default 0
     **/
    this.currentAnimationFrame = 0;
  
    /**
     * By default Sprite instances advance one frame per tick. Specifying a framerate for the Sprite (or its related
     * SpriteSheet) will cause it to advance based on elapsed time between ticks as appropriate to maintain the target
     * framerate.
     *
     * For example, if a Sprite with a framerate of 10 is placed on a Stage being updated at 40fps, then the Sprite will
     * advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will
     * vary slightly between frames.
     *
     * This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being
     * passed into {{#crossLink "Stage/update"}}{{/crossLink}}.
     * @property framerate
     * @type {Number}
     * @default 0
     **/
    this.framerate = 0;
  
  
  // private properties:
    /**
     * Current animation object.
     * @property _animation
     * @protected
     * @type {Object}
     * @default null
     **/
    this._animation = null;
  
    /**
     * Current frame index.
     * @property _currentFrame
     * @protected
     * @type {Number}
     * @default null
     **/
    this._currentFrame = null;
    
    /**
     * Skips the next auto advance. Used by gotoAndPlay to avoid immediately jumping to the next frame
     * @property _skipAdvance
     * @protected
     * @type {Boolean}
     * @default false
     **/
    this._skipAdvance = false;
    
    
    if (frameOrAnimation != null) { this.gotoAndPlay(frameOrAnimation); }
  }
  var p = createjs.extend(Sprite, createjs.DisplayObject);

  /**
   * Constructor alias for backwards compatibility. This method will be removed in future versions.
   * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
   * @method initialize
   * @deprecated in favour of `createjs.promote()`
   **/
  p.initialize = Sprite; // TODO: Deprecated. This is for backwards support of FlashCC spritesheet export.


// events:
  /**
   * Dispatched when an animation reaches its ends.
   * @event animationend
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {String} name The name of the animation that just ended.
   * @param {String} next The name of the next animation that will be played, or null. This will be the same as name if the animation is looping.
   * @since 0.6.0
   */
   
  /**
   * Dispatched any time the current frame changes. For example, this could be due to automatic advancement on a tick,
   * or calling gotoAndPlay() or gotoAndStop().
   * @event change
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   */


// public methods:
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var hasContent = this.cacheCanvas || this.spriteSheet.complete;
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
   * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
   * into itself).
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
    this._normalizeFrame();
    var o = this.spriteSheet.getFrame(this._currentFrame|0);
    if (!o) { return false; }
    var rect = o.rect;
    if (rect.width && rect.height) { ctx.drawImage(o.image, rect.x, rect.y, rect.width, rect.height, -o.regX, -o.regY, rect.width, rect.height); }
    return true;
  };

  //Note, the doc sections below document using the specified APIs (from DisplayObject)  from
  //Bitmap. This is why they have no method implementations.

  /**
   * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
   * You should not cache Sprite instances as it can degrade performance.
   * @method cache
   **/

  /**
   * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
   * You should not cache Sprite instances as it can degrade performance.
   * @method updateCache
   **/

  /**
   * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
   * You should not cache Sprite instances as it can degrade performance.
   * @method uncache
   **/

  /**
   * Play (unpause) the current animation. The Sprite will be paused if either {{#crossLink "Sprite/stop"}}{{/crossLink}}
   * or {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} is called. Single frame animations will remain
   * unchanged.
   * @method play
   **/
  p.play = function() {
    this.paused = false;
  };

  /**
   * Stop playing a running animation. The Sprite will be playing if {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}
   * is called. Note that calling {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} or {{#crossLink "Sprite/play"}}{{/crossLink}}
   * will resume playback.
   * @method stop
   **/
  p.stop = function() {
    this.paused = true;
  };

  /**
   * Sets paused to false and plays the specified animation name, named frame, or frame number.
   * @method gotoAndPlay
   * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to
   * and begin playing.
   **/
  p.gotoAndPlay = function(frameOrAnimation) {
    this.paused = false;
    this._skipAdvance = true;
    this._goto(frameOrAnimation);
  };

  /**
   * Sets paused to true and seeks to the specified animation name, named frame, or frame number.
   * @method gotoAndStop
   * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to
   * and stop.
   **/
  p.gotoAndStop = function(frameOrAnimation) {
    this.paused = true;
    this._goto(frameOrAnimation);
  };

  /**
   * Advances the playhead. This occurs automatically each tick by default.
   * @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set on the Sprite
   * or its SpriteSheet.
   * @method advance
  */
  p.advance = function(time) {
    var fps = this.framerate || this.spriteSheet.framerate;
    var t = (fps && time != null) ? time/(1000/fps) : 1;
    this._normalizeFrame(t);
  };
  
  /**
   * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the current frame relative to
   * the origin. For example, a 90 x 70 frame with <code>regX=50</code> and <code>regY=40</code> would return a
   * rectangle with [x=-50, y=-40, width=90, height=70]. This ignores transformations on the display object.
   *
   * Also see the SpriteSheet {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} method.
   * @method getBounds
   * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully
   * loaded.
   **/
  p.getBounds = function() {
    // TODO: should this normalizeFrame?
    return this.DisplayObject_getBounds() || this.spriteSheet.getFrameBounds(this.currentFrame, this._rectangle);
  };

  /**
   * Returns a clone of the Sprite instance. Note that the same SpriteSheet is shared between cloned
   * instances.
   * @method clone
   * @return {Sprite} a clone of the Sprite instance.
   **/
  p.clone = function() {
    return this._cloneProps(new Sprite(this.spriteSheet));
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Sprite (name="+  this.name +")]";
  };

// private methods:
  /**
   * @method _cloneProps
   * @param {Sprite} o
   * @return {Sprite} o
   * @protected
   **/
  p._cloneProps = function(o) {
    this.DisplayObject__cloneProps(o);
    o.currentFrame = this.currentFrame;
    o.currentAnimation = this.currentAnimation;
    o.paused = this.paused;
    o.currentAnimationFrame = this.currentAnimationFrame;
    o.framerate = this.framerate;
    
    o._animation = this._animation;
    o._currentFrame = this._currentFrame;
    o._skipAdvance = this._skipAdvance;
    return o;
  };
  
  /**
   * Advances the <code>currentFrame</code> if paused is not true. This is called automatically when the {{#crossLink "Stage"}}{{/crossLink}}
   * ticks.
   * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs.
   * @protected
   * @method _tick
   **/
  p._tick = function(evtObj) {
    if (!this.paused) {
      if (!this._skipAdvance) { this.advance(evtObj&&evtObj.delta); }
      this._skipAdvance = false;
    }
    this.DisplayObject__tick(evtObj);
  };


  /**
   * Normalizes the current frame, advancing animations and dispatching callbacks as appropriate.
   * @protected
   * @method _normalizeFrame
   **/
  p._normalizeFrame = function(frameDelta) {
    frameDelta = frameDelta || 0;
    var animation = this._animation;
    var paused = this.paused;
    var frame = this._currentFrame;
    var l;
    
    if (animation) {
      var speed = animation.speed || 1;
      var animFrame = this.currentAnimationFrame;
      l = animation.frames.length;
      if (animFrame + frameDelta * speed >= l) {
        var next = animation.next;
        if (this._dispatchAnimationEnd(animation, frame, paused, next, l - 1)) {
          // something changed in the event stack, so we shouldn't make any more changes here.
          return;
        } else if (next) {
          // sequence. Automatically calls _normalizeFrame again with the remaining frames.
          return this._goto(next, frameDelta - (l - animFrame) / speed);
        } else {
          // end.
          this.paused = true;
          animFrame = animation.frames.length - 1;
        }
      } else {
        animFrame += frameDelta * speed;
      }
      this.currentAnimationFrame = animFrame;
      this._currentFrame = animation.frames[animFrame | 0]
    } else {
      frame = (this._currentFrame += frameDelta);
      l = this.spriteSheet.getNumFrames();
      if (frame >= l && l > 0) {
        if (!this._dispatchAnimationEnd(animation, frame, paused, l - 1)) {
          // looped.
          if ((this._currentFrame -= l) >= l) { return this._normalizeFrame(); }
        }
      }
    }
    frame = this._currentFrame | 0;
    if (this.currentFrame != frame) {
      this.currentFrame = frame;
      this.dispatchEvent("change");
    }
  };

  /**
   * Dispatches the "animationend" event. Returns true if a handler changed the animation (ex. calling {{#crossLink "Sprite/stop"}}{{/crossLink}},
   * {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, etc.)
   * @property _dispatchAnimationEnd
   * @private
   * @type {Function}
   **/
  p._dispatchAnimationEnd = function(animation, frame, paused, next, end) {
    var name = animation ? animation.name : null;
    if (this.hasEventListener("animationend")) {
      var evt = new createjs.Event("animationend");
      evt.name = name;
      evt.next = next;
      this.dispatchEvent(evt);
    }
    // did the animation get changed in the event stack?:
    var changed = (this._animation != animation || this._currentFrame != frame);
    // if the animation hasn't changed, but the sprite was paused, then we want to stick to the last frame:
    if (!changed && !paused && this.paused) { this.currentAnimationFrame = end; changed = true; }
    return changed;
  };

  /**
   * Moves the playhead to the specified frame number or animation.
   * @method _goto
   * @param {String|Number} frameOrAnimation The frame number or animation that the playhead should move to.
   * @param {Boolean} [frame] The frame of the animation to go to. Defaults to 0.
   * @protected
   **/
  p._goto = function(frameOrAnimation, frame) {
    this.currentAnimationFrame = 0;
    if (isNaN(frameOrAnimation)) {
      var data = this.spriteSheet.getAnimation(frameOrAnimation);
      if (data) {
        this._animation = data;
        this.currentAnimation = frameOrAnimation;
        this._normalizeFrame(frame);
      }
    } else {
      this.currentAnimation = this._animation = null;
      this._currentFrame = frameOrAnimation;
      this._normalizeFrame();
    }
  };


  createjs.Sprite = createjs.promote(Sprite, "DisplayObject");
}());

//##############################################################################
// Shape.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * A Shape allows you to display vector art in the display list. It composites a {{#crossLink "Graphics"}}{{/crossLink}}
   * instance which exposes all of the vector drawing methods. The Graphics instance can be shared between multiple Shape
   * instances to display the same vector graphics with different positions or transforms.
   *
   * If the vector art will not
   * change between draws, you may want to use the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method to reduce the
   * rendering cost.
   *
   * <h4>Example</h4>
   *
   *      var graphics = new createjs.Graphics().beginFill("#ff0000").drawRect(0, 0, 100, 100);
   *      var shape = new createjs.Shape(graphics);
   *
   *      //Alternatively use can also use the graphics property of the Shape class to renderer the same as above.
   *      var shape = new createjs.Shape();
   *      shape.graphics.beginFill("#ff0000").drawRect(0, 0, 100, 100);
   *
   * @class Shape
   * @extends DisplayObject
   * @constructor
   * @param {Graphics} graphics Optional. The graphics instance to display. If null, a new Graphics instance will be created.
   **/
  function Shape(graphics) {
    this.DisplayObject_constructor();
    
    
  // public properties:
    /**
     * The graphics instance to display.
     * @property graphics
     * @type Graphics
     **/
    this.graphics = graphics ? graphics : new createjs.Graphics();
  }
  var p = createjs.extend(Shape, createjs.DisplayObject);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// public methods:
  /**
   * Returns true or false indicating whether the Shape would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the Shape would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var hasContent = this.cacheCanvas || (this.graphics && !this.graphics.isEmpty());
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
  };

  /**
   * Draws the Shape into the specified context ignoring its visible, alpha, shadow, and transform. Returns true if
   * the draw was handled (useful for overriding functionality).
   *
   * <i>NOTE: This method is mainly for internal use, though it may be useful for advanced uses.</i>
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example,
   * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself).
   * @return {Boolean}
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
    this.graphics.draw(ctx, this);
    return true;
  };

  /**
   * Returns a clone of this Shape. Some properties that are specific to this instance's current context are reverted to
   * their defaults (for example .parent).
   * @method clone
   * @param {Boolean} recursive If true, this Shape's {{#crossLink "Graphics"}}{{/crossLink}} instance will also be
   * cloned. If false, the Graphics instance will be shared with the new Shape.
   **/
  p.clone = function(recursive) {
    var g = (recursive && this.graphics) ? this.graphics.clone() : this.graphics;
    return  this._cloneProps(new Shape(g));
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Shape (name="+  this.name +")]";
  };


  createjs.Shape = createjs.promote(Shape, "DisplayObject");
}());

//##############################################################################
// Text.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Display one or more lines of dynamic text (not user editable) in the display list. Line wrapping support (using the
   * lineWidth) is very basic, wrapping on spaces and tabs only. Note that as an alternative to Text, you can position HTML
   * text above or below the canvas relative to items in the display list using the {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}}
   * method, or using {{#crossLink "DOMElement"}}{{/crossLink}}.
   *
   * <b>Please note that Text does not support HTML text, and can only display one font style at a time.</b> To use
   * multiple font styles, you will need to create multiple text instances, and position them manually.
   *
   * <h4>Example</h4>
   *
   *      var text = new createjs.Text("Hello World", "20px Arial", "#ff7700");
   *      text.x = 100;
   *      text.textBaseline = "alphabetic";
   *
   * CreateJS Text supports web fonts (the same rules as Canvas). The font must be loaded and supported by the browser
   * before it can be displayed.
   *
   * <strong>Note:</strong> Text can be expensive to generate, so cache instances where possible. Be aware that not all
   * browsers will render Text exactly the same.
   * @class Text
   * @extends DisplayObject
   * @constructor
   * @param {String} [text] The text to display.
   * @param {String} [font] The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold
   * 36px Arial").
   * @param {String} [color] The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex.
   * "#F00", "red", or "#FF0000").
   **/
  function Text(text, font, color) {
    this.DisplayObject_constructor();
    
    
  // public properties:
    /**
     * The text to display.
     * @property text
     * @type String
     **/
    this.text = text;
  
    /**
     * The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold 36px Arial").
     * @property font
     * @type String
     **/
    this.font = font;
  
    /**
     * The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. "#F00"). Default is "#000".
     * It will also accept valid canvas fillStyle values.
     * @property color
     * @type String
     **/
    this.color = color;
  
    /**
     * The horizontal text alignment. Any of "start", "end", "left", "right", and "center". For detailed
     * information view the
     * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
     * whatwg spec</a>. Default is "left".
     * @property textAlign
     * @type String
     **/
    this.textAlign = "left";
  
    /**
     * The vertical alignment point on the font. Any of "top", "hanging", "middle", "alphabetic", "ideographic", or
     * "bottom". For detailed information view the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
     * whatwg spec</a>. Default is "top".
     * @property textBaseline
     * @type String
    */
    this.textBaseline = "top";
  
    /**
     * The maximum width to draw the text. If maxWidth is specified (not null), the text will be condensed or
     * shrunk to make it fit in this width. For detailed information view the
     * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
     * whatwg spec</a>.
     * @property maxWidth
     * @type Number
    */
    this.maxWidth = null;
  
    /**
     * If greater than 0, the text will be drawn as a stroke (outline) of the specified width.
     * @property outline
     * @type Number
     **/
    this.outline = 0;
  
    /**
     * Indicates the line height (vertical distance between baselines) for multi-line text. If null or 0,
     * the value of getMeasuredLineHeight is used.
     * @property lineHeight
     * @type Number
     **/
    this.lineHeight = 0;
  
    /**
     * Indicates the maximum width for a line of text before it is wrapped to multiple lines. If null,
     * the text will not be wrapped.
     * @property lineWidth
     * @type Number
     **/
    this.lineWidth = null;
  }
  var p = createjs.extend(Text, createjs.DisplayObject);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.

  
// static properties:
  /**
   * @property _workingContext
   * @type CanvasRenderingContext2D
   * @private
   **/
  var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
  if (canvas.getContext) { Text._workingContext = canvas.getContext("2d"); canvas.width = canvas.height = 1; }
  
  
// constants:
  /**
   * Lookup table for the ratio to offset bounds x calculations based on the textAlign property.
   * @property H_OFFSETS
   * @type Object
   * @protected
   * @static
   **/
  Text.H_OFFSETS = {start: 0, left: 0, center: -0.5, end: -1, right: -1};
  
  /**
   * Lookup table for the ratio to offset bounds y calculations based on the textBaseline property.
   * @property H_OFFSETS
   * @type Object
   * @protected
   * @static
   **/
  Text.V_OFFSETS = {top: 0, hanging: -0.01, middle: -0.4, alphabetic: -0.8, ideographic: -0.85, bottom: -1};


// public methods:
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var hasContent = this.cacheCanvas || (this.text != null && this.text !== "");
    return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
  };

  /**
   * Draws the Text into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
   * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
   * into itself).
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }

    var col = this.color || "#000";
    if (this.outline) { ctx.strokeStyle = col; ctx.lineWidth = this.outline*1; }
    else { ctx.fillStyle = col; }
    
    this._drawText(this._prepContext(ctx));
    return true;
  };

  /**
   * Returns the measured, untransformed width of the text without wrapping. Use getBounds for a more robust value.
   * @method getMeasuredWidth
   * @return {Number} The measured, untransformed width of the text.
   **/
  p.getMeasuredWidth = function() {
    return this._getMeasuredWidth(this.text);
  };

  /**
   * Returns an approximate line height of the text, ignoring the lineHeight property. This is based on the measured
   * width of a "M" character multiplied by 1.2, which provides an approximate line height for most fonts.
   * @method getMeasuredLineHeight
   * @return {Number} an approximate line height of the text, ignoring the lineHeight property. This is
   * based on the measured width of a "M" character multiplied by 1.2, which approximates em for most fonts.
   **/
  p.getMeasuredLineHeight = function() {
    return this._getMeasuredWidth("M")*1.2;
  };

  /**
   * Returns the approximate height of multi-line text by multiplying the number of lines against either the
   * <code>lineHeight</code> (if specified) or {{#crossLink "Text/getMeasuredLineHeight"}}{{/crossLink}}. Note that
   * this operation requires the text flowing logic to run, which has an associated CPU cost.
   * @method getMeasuredHeight
   * @return {Number} The approximate height of the untransformed multi-line text.
   **/
  p.getMeasuredHeight = function() {
    return this._drawText(null,{}).height;
  };

  /**
   * Docced in superclass.
   */
  p.getBounds = function() {
    var rect = this.DisplayObject_getBounds();
    if (rect) { return rect; }
    if (this.text == null || this.text === "") { return null; }
    var o = this._drawText(null, {});
    var w = (this.maxWidth && this.maxWidth < o.width) ? this.maxWidth : o.width;
    var x = w * Text.H_OFFSETS[this.textAlign||"left"];
    var lineHeight = this.lineHeight||this.getMeasuredLineHeight();
    var y = lineHeight * Text.V_OFFSETS[this.textBaseline||"top"];
    return this._rectangle.setValues(x, y, w, o.height);
  };
  
  /**
   * Returns an object with width, height, and lines properties. The width and height are the visual width and height
   * of the drawn text. The lines property contains an array of strings, one for
   * each line of text that will be drawn, accounting for line breaks and wrapping. These strings have trailing
   * whitespace removed.
   * @method getMetrics
   * @return {Object} An object with width, height, and lines properties.
   **/
  p.getMetrics = function() {
    var o = {lines:[]};
    o.lineHeight = this.lineHeight || this.getMeasuredLineHeight();
    o.vOffset = o.lineHeight * Text.V_OFFSETS[this.textBaseline||"top"];
    return this._drawText(null, o, o.lines);
  };

  /**
   * Returns a clone of the Text instance.
   * @method clone
   * @return {Text} a clone of the Text instance.
   **/
  p.clone = function() {
    return this._cloneProps(new Text(this.text, this.font, this.color));
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Text (text="+  (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]";
  };


// private methods:
  /**
   * @method _cloneProps
   * @param {Text} o
   * @protected
   * @return {Text} o
   **/
  p._cloneProps = function(o) {
    this.DisplayObject__cloneProps(o);
    o.textAlign = this.textAlign;
    o.textBaseline = this.textBaseline;
    o.maxWidth = this.maxWidth;
    o.outline = this.outline;
    o.lineHeight = this.lineHeight;
    o.lineWidth = this.lineWidth;
    return o;
  };

  /**
   * @method _getWorkingContext
   * @param {CanvasRenderingContext2D} ctx
   * @return {CanvasRenderingContext2D}
   * @protected
   **/
  p._prepContext = function(ctx) {
    ctx.font = this.font||"10px sans-serif";
    ctx.textAlign = this.textAlign||"left";
    ctx.textBaseline = this.textBaseline||"top";
    return ctx;
  };

  /**
   * Draws multiline text.
   * @method _drawText
   * @param {CanvasRenderingContext2D} ctx
   * @param {Object} o
   * @param {Array} lines
   * @return {Object}
   * @protected
   **/
  p._drawText = function(ctx, o, lines) {
    var paint = !!ctx;
    if (!paint) {
      ctx = Text._workingContext;
      ctx.save();
      this._prepContext(ctx);
    }
    var lineHeight = this.lineHeight||this.getMeasuredLineHeight();
    
    var maxW = 0, count = 0;
    var hardLines = String(this.text).split(/(?:\r\n|\r|\n)/);
    for (var i=0, l=hardLines.length; i<l; i++) {
      var str = hardLines[i];
      var w = null;
      
      if (this.lineWidth != null && (w = ctx.measureText(str).width) > this.lineWidth) {
        // text wrapping:
        var words = str.split(/(\s)/);
        str = words[0];
        w = ctx.measureText(str).width;
        
        for (var j=1, jl=words.length; j<jl; j+=2) {
          // Line needs to wrap:
          var wordW = ctx.measureText(words[j] + words[j+1]).width;
          if (w + wordW > this.lineWidth) {
            if (paint) { this._drawTextLine(ctx, str, count*lineHeight); }
            if (lines) { lines.push(str); }
            if (w > maxW) { maxW = w; }
            str = words[j+1];
            w = ctx.measureText(str).width;
            count++;
          } else {
            str += words[j] + words[j+1];
            w += wordW;
          }
        }
      }
      
      if (paint) { this._drawTextLine(ctx, str, count*lineHeight); }
      if (lines) { lines.push(str); }
      if (o && w == null) { w = ctx.measureText(str).width; }
      if (w > maxW) { maxW = w; }
      count++;
    }
    
    if (o) {
      o.width = maxW;
      o.height = count*lineHeight;
    }
    if (!paint) { ctx.restore(); }
    return o;
  };

  /**
   * @method _drawTextLine
   * @param {CanvasRenderingContext2D} ctx
   * @param {String} text
   * @param {Number} y
   * @protected
   **/
  p._drawTextLine = function(ctx, text, y) {
    // Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
    if (this.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); }
    else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); }
  };
  
  
  /**
   * @method _getMeasuredWidth
   * @param {String} text
   * @protected
   **/
  p._getMeasuredWidth = function(text) {
    var ctx = Text._workingContext;
    ctx.save();
    var w = this._prepContext(ctx).measureText(text).width;
    ctx.restore();
    return w;
  };


  createjs.Text = createjs.promote(Text, "DisplayObject");
}());

//##############################################################################
// BitmapText.js
//##############################################################################

(function () {
  "use strict";


// constructor:
  /**
   * Displays text using bitmap glyphs defined in a sprite sheet. Multi-line text is supported
   * using new line characters, but automatic wrapping is not supported. See the 
   * {{#crossLink "BitmapText/spriteSheet:property"}}{{/crossLink}}
   * property for more information on defining glyphs.
   * 
   * <strong>Important:</strong> BitmapText extends Container, but is not designed to be used as one.
   * As such, methods like addChild and removeChild are disabled.
   * @class BitmapText
   * @extends DisplayObject
   * @param {String} [text=""] The text to display.
   * @param {SpriteSheet} [spriteSheet=null] The spritesheet that defines the character glyphs.
   * @constructor
   **/
  function BitmapText(text, spriteSheet) {
    this.Container_constructor();
    
    
  // public properties:
    /**
     * The text to display.
     * @property text
     * @type String
     * @default ""
     **/
    this.text = text||"";
    
    /**
     * A SpriteSheet instance that defines the glyphs for this bitmap text. Each glyph/character
     * should have a single frame animation defined in the sprite sheet named the same as
     * corresponding character. For example, the following animation definition:
     *
     *    "A": {frames: [0]}
     *
     * would indicate that the frame at index 0 of the spritesheet should be drawn for the "A" character. The short form
     * is also acceptable:
     * 
     *    "A": 0
     *
     * Note that if a character in the text is not found in the sprite sheet, it will also
     * try to use the alternate case (upper or lower).
     *
     * See SpriteSheet for more information on defining sprite sheet data.
     * @property spriteSheet
     * @type SpriteSheet
     * @default null
     **/
    this.spriteSheet = spriteSheet;
  
    /**
     * The height of each line of text. If 0, then it will use a line height calculated
     * by checking for the height of the "1", "T", or "L" character (in that order). If
     * those characters are not defined, it will use the height of the first frame of the
     * sprite sheet.
     * @property lineHeight
     * @type Number
     * @default 0
     **/
    this.lineHeight = 0;
  
    /**
     * This spacing (in pixels) will be added after each character in the output.
     * @property letterSpacing
     * @type Number
     * @default 0
     **/
    this.letterSpacing = 0;
  
    /**
     * If a space character is not defined in the sprite sheet, then empty pixels equal to
     * spaceWidth will be inserted instead. If 0, then it will use a value calculated
     * by checking for the width of the "1", "l", "E", or "A" character (in that order). If
     * those characters are not defined, it will use the width of the first frame of the
     * sprite sheet.
     * @property spaceWidth
     * @type Number
     * @default 0
     **/
    this.spaceWidth = 0;
    
    
  // private properties:
    /**
     * @property _oldProps
     * @type Object
     * @protected
     **/
    this._oldProps = {text:0,spriteSheet:0,lineHeight:0,letterSpacing:0,spaceWidth:0};
  }
  var p = createjs.extend(BitmapText, createjs.Container);

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.

// static properties:
  /**
   * BitmapText uses Sprite instances to draw text. To reduce the creation and destruction of instances (and thus garbage collection), it maintains
   * an internal object pool of sprite instances to reuse. Increasing this value can cause more sprites to be
   * retained, slightly increasing memory use, but reducing instantiation.
   * @property maxPoolSize
   * @type Number
   * @static
   * @default 100
   **/
  BitmapText.maxPoolSize = 100;
  
  /**
   * Sprite object pool.
   * @type {Array}
   * @static
   * @private
   */
  BitmapText._spritePool = [];

  
// public methods:
  /**
   * Docced in superclass.
   **/
  p.draw = function(ctx, ignoreCache) {
    if (this.DisplayObject_draw(ctx, ignoreCache)) { return; }
    this._updateText();
    this.Container_draw(ctx, ignoreCache);
  };
  
  /**
   * Docced in superclass.
   **/
  p.getBounds = function() {
    this._updateText();
    return this.Container_getBounds();
  };
  
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   **/
  p.isVisible = function() {
    var hasContent = this.cacheCanvas || (this.spriteSheet && this.spriteSheet.complete && this.text);
    return !!(this.visible && this.alpha > 0 && this.scaleX !== 0 && this.scaleY !== 0 && hasContent);
  };
  
  p.clone = function() {
    return this._cloneProps(new BitmapText(this.text, this.spriteSheet));
  };
  
  /**
   * <strong>Disabled in BitmapText.</strong>
   * @method addChild
   **/
  /**
   * <strong>Disabled in BitmapText.</strong>
   * @method addChildAt
   **/
  /**
   * <strong>Disabled in BitmapText.</strong>
   * @method removeChild
   **/
  /**
   * <strong>Disabled in BitmapText.</strong>
   * @method removeChildAt
   **/
  /**
   * <strong>Disabled in BitmapText.</strong>
   * @method removeAllChildren
   **/
  p.addChild = p.addChildAt = p.removeChild = p.removeChildAt = p.removeAllChildren = function() {};


// private methods:
  /**
   * @method _cloneProps
   * @param {BitmapText} o
   * @return {BitmapText} o
   * @protected
   **/
  p._cloneProps = function(o) {
    this.Container__cloneProps(o);
    o.lineHeight = this.lineHeight;
    o.letterSpacing = this.letterSpacing;
    o.spaceWidth = this.spaceWidth;
    return o;
  };
  
  /**
   * @method _getFrameIndex
   * @param {String} character
   * @param {SpriteSheet} spriteSheet
   * @return {Number}
   * @protected
   **/
  p._getFrameIndex = function(character, spriteSheet) {
    var c, o = spriteSheet.getAnimation(character);
    if (!o) {
      (character != (c = character.toUpperCase())) || (character != (c = character.toLowerCase())) || (c=null);
      if (c) { o = spriteSheet.getAnimation(c); }
    }
    return o && o.frames[0];
  };
  
  /**
   * @method _getFrame
   * @param {String} character
   * @param {SpriteSheet} spriteSheet
   * @return {Object}
   * @protected
   **/
  p._getFrame = function(character, spriteSheet) {
    var index = this._getFrameIndex(character, spriteSheet);
    return index == null ? index : spriteSheet.getFrame(index);
  };
  
  /**
   * @method _getLineHeight
   * @param {SpriteSheet} ss
   * @return {Number}
   * @protected
   **/
  p._getLineHeight = function(ss) {
    var frame = this._getFrame("1",ss) || this._getFrame("T",ss) || this._getFrame("L",ss) || ss.getFrame(0);
    return frame ? frame.rect.height : 1;
  };
  /**
   * @method _getSpaceWidth
   * @param {SpriteSheet} ss
   * @return {Number}
   * @protected
   **/
  p._getSpaceWidth = function(ss) {
    var frame = this._getFrame("1",ss) || this._getFrame("l",ss) || this._getFrame("e",ss) || this._getFrame("a",ss) || ss.getFrame(0);
    return frame ? frame.rect.width : 1;
  };
  
  /**
   * @method _drawText
   * @protected
   **/
  p._updateText = function() {
    var x=0, y=0, o=this._oldProps, change=false, spaceW=this.spaceWidth, lineH=this.lineHeight, ss=this.spriteSheet;
    var pool=BitmapText._spritePool, kids=this.children, childIndex=0, numKids=kids.length, sprite;
    
    for (var n in o) {
      if (o[n] != this[n]) {
        o[n] = this[n];
        change = true;
      }
    }
    if (!change) { return; }
    
    var hasSpace = !!this._getFrame(" ", ss);
    if (!hasSpace && !spaceW) { spaceW = this._getSpaceWidth(ss); }
    if (!lineH) { lineH = this._getLineHeight(ss); }
    
    for(var i=0, l=this.text.length; i<l; i++) {
      var character = this.text.charAt(i);
      if (character == " " && !hasSpace) {
        x += spaceW;
        continue;
      } else if (character=="\n" || character=="\r") {
        if (character=="\r" && this.text.charAt(i+1) == "\n") { i++; } // crlf
        x = 0;
        y += lineH;
        continue;
      }

      var index = this._getFrameIndex(character, ss);
      if (index == null) { continue; }
      
      if (childIndex < numKids) {
        sprite = kids[childIndex];
      } else {
        kids.push(sprite = pool.length ? pool.pop() : new createjs.Sprite());
        sprite.parent = this;
        numKids++;
      }
      sprite.spriteSheet = ss;
      sprite.gotoAndStop(index);
      sprite.x = x;
      sprite.y = y;
      childIndex++;
      
      x += sprite.getBounds().width + this.letterSpacing;
    }
    while (numKids > childIndex) {
       // faster than removeChild.
      pool.push(sprite = kids.pop());
      sprite.parent = null;
      numKids--;
    }
    if (pool.length > BitmapText.maxPoolSize) { pool.length = BitmapText.maxPoolSize; }
  };


  createjs.BitmapText = createjs.promote(BitmapText, "Container");
}());

//##############################################################################
// SpriteSheetUtils.js
//##############################################################################

(function() {
  "use strict";
  
  
// constructor:
  /**
   * The SpriteSheetUtils class is a collection of static methods for working with {{#crossLink "SpriteSheet"}}{{/crossLink}}s.
   * A sprite sheet is a series of images (usually animation frames) combined into a single image on a regular grid. For
   * example, an animation consisting of 8 100x100 images could be combined into a 400x200 sprite sheet (4 frames across
   * by 2 high). The SpriteSheetUtils class uses a static interface and should not be instantiated.
   * @class SpriteSheetUtils
   * @static
   **/
  function SpriteSheetUtils() {
    throw "SpriteSheetUtils cannot be instantiated";
  }


// private static properties:
  /**
   * @property _workingCanvas
   * @static
   * @type HTMLCanvasElement | Object
   * @protected
  */
  /**
   * @property _workingContext
   * @static
   * @type CanvasRenderingContext2D
   * @protected
  */
  var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
  if (canvas.getContext) {
    SpriteSheetUtils._workingCanvas = canvas;
    SpriteSheetUtils._workingContext = canvas.getContext("2d");
    canvas.width = canvas.height = 1;
  }


// public static methods:
  /**
   * <b>This is an experimental method, and may be buggy. Please report issues.</b><br/><br/>
   * Extends the existing sprite sheet by flipping the original frames horizontally, vertically, or both,
   * and adding appropriate animation & frame data. The flipped animations will have a suffix added to their names
   * (_h, _v, _hv as appropriate). Make sure the sprite sheet images are fully loaded before using this method.
   * <br/><br/>
   * For example:<br/>
   * SpriteSheetUtils.addFlippedFrames(mySpriteSheet, true, true);
   * The above would add frames that are flipped horizontally AND frames that are flipped vertically.
   * <br/><br/>
   * Note that you can also flip any display object by setting its scaleX or scaleY to a negative value. On some
   * browsers (especially those without hardware accelerated canvas) this can result in slightly degraded performance,
   * which is why addFlippedFrames is available.
   * @method addFlippedFrames
   * @static
   * @param {SpriteSheet} spriteSheet
   * @param {Boolean} horizontal If true, horizontally flipped frames will be added.
   * @param {Boolean} vertical If true, vertically flipped frames will be added.
   * @param {Boolean} both If true, frames that are flipped both horizontally and vertically will be added.
   * @deprecated Modern browsers perform better when flipping via a transform (ex. scaleX=-1) rendering this obsolete.
   **/
  SpriteSheetUtils.addFlippedFrames = function(spriteSheet, horizontal, vertical, both) {
    if (!horizontal && !vertical && !both) { return; }

    var count = 0;
    if (horizontal) { SpriteSheetUtils._flip(spriteSheet,++count,true,false); }
    if (vertical) { SpriteSheetUtils._flip(spriteSheet,++count,false,true); }
    if (both) { SpriteSheetUtils._flip(spriteSheet,++count,true,true); }
  };

  /**
   * Returns a single frame of the specified sprite sheet as a new PNG image. An example of when this may be useful is
   * to use a spritesheet frame as the source for a bitmap fill.
   *
   * <strong>WARNING:</strong> In almost all cases it is better to display a single frame using a {{#crossLink "Sprite"}}{{/crossLink}}
   * with a {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} call than it is to slice out a frame using this
   * method and display it with a Bitmap instance. You can also crop an image using the {{#crossLink "Bitmap/sourceRect"}}{{/crossLink}}
   * property of {{#crossLink "Bitmap"}}{{/crossLink}}.
   *
   * The extractFrame method may cause cross-domain warnings since it accesses pixels directly on the canvas.
   * @method extractFrame
   * @static
   * @param {SpriteSheet} spriteSheet The SpriteSheet instance to extract a frame from.
   * @param {Number|String} frameOrAnimation The frame number or animation name to extract. If an animation
   * name is specified, only the first frame of the animation will be extracted.
   * @return {HTMLImageElement} a single frame of the specified sprite sheet as a new PNG image.
  */
  SpriteSheetUtils.extractFrame = function(spriteSheet, frameOrAnimation) {
    if (isNaN(frameOrAnimation)) {
      frameOrAnimation = spriteSheet.getAnimation(frameOrAnimation).frames[0];
    }
    var data = spriteSheet.getFrame(frameOrAnimation);
    if (!data) { return null; }
    var r = data.rect;
    var canvas = SpriteSheetUtils._workingCanvas;
    canvas.width = r.width;
    canvas.height = r.height;
    SpriteSheetUtils._workingContext.drawImage(data.image, r.x, r.y, r.width, r.height, 0, 0, r.width, r.height);
    var img = document.createElement("img");
    img.src = canvas.toDataURL("image/png");
    return img;
  };

  /**
   * Merges the rgb channels of one image with the alpha channel of another. This can be used to combine a compressed
   * JPEG image containing color data with a PNG32 monochromatic image containing alpha data. With certain types of
   * images (those with detail that lend itself to JPEG compression) this can provide significant file size savings
   * versus a single RGBA PNG32. This method is very fast (generally on the order of 1-2 ms to run).
   * @method mergeAlpha
   * @static
   * @param {HTMLImageElement} rbgImage The image (or canvas) containing the RGB channels to use.
   * @param {HTMLImageElement} alphaImage The image (or canvas) containing the alpha channel to use.
   * @param {HTMLCanvasElement} canvas Optional. If specified, this canvas will be used and returned. If not, a new canvas will be created.
   * @return {HTMLCanvasElement} A canvas with the combined image data. This can be used as a source for Bitmap or SpriteSheet.
   * @deprecated Tools such as ImageAlpha generally provide better results. This will be moved to sandbox in the future.
  */
  SpriteSheetUtils.mergeAlpha = function(rgbImage, alphaImage, canvas) {
    if (!canvas) { canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); }
    canvas.width = Math.max(alphaImage.width, rgbImage.width);
    canvas.height = Math.max(alphaImage.height, rgbImage.height);
    var ctx = canvas.getContext("2d");
    ctx.save();
    ctx.drawImage(rgbImage,0,0);
    ctx.globalCompositeOperation = "destination-in";
    ctx.drawImage(alphaImage,0,0);
    ctx.restore();
    return canvas;
  };


// private static methods:
  SpriteSheetUtils._flip = function(spriteSheet, count, h, v) {
    var imgs = spriteSheet._images;
    var canvas = SpriteSheetUtils._workingCanvas;
    var ctx = SpriteSheetUtils._workingContext;
    var il = imgs.length/count;
    for (var i=0;i<il;i++) {
      var src = imgs[i];
      src.__tmp = i; // a bit hacky, but faster than doing indexOf below.
      ctx.setTransform(1,0,0,1,0,0);
      ctx.clearRect(0,0,canvas.width+1,canvas.height+1);
      canvas.width = src.width;
      canvas.height = src.height;
      ctx.setTransform(h?-1:1, 0, 0, v?-1:1, h?src.width:0, v?src.height:0);
      ctx.drawImage(src,0,0);
      var img = document.createElement("img");
      img.src = canvas.toDataURL("image/png");
      // work around a strange bug in Safari:
      img.width = src.width;
      img.height = src.height;
      imgs.push(img);
    }

    var frames = spriteSheet._frames;
    var fl = frames.length/count;
    for (i=0;i<fl;i++) {
      src = frames[i];
      var rect = src.rect.clone();
      img = imgs[src.image.__tmp+il*count];

      var frame = {image:img,rect:rect,regX:src.regX,regY:src.regY};
      if (h) {
        rect.x = img.width-rect.x-rect.width; // update rect
        frame.regX = rect.width-src.regX; // update registration point
      }
      if (v) {
        rect.y = img.height-rect.y-rect.height;  // update rect
        frame.regY = rect.height-src.regY; // update registration point
      }
      frames.push(frame);
    }

    var sfx = "_"+(h?"h":"")+(v?"v":"");
    var names = spriteSheet._animations;
    var data = spriteSheet._data;
    var al = names.length/count;
    for (i=0;i<al;i++) {
      var name = names[i];
      src = data[name];
      var anim = {name:name+sfx,speed:src.speed,next:src.next,frames:[]};
      if (src.next) { anim.next += sfx; }
      frames = src.frames;
      for (var j=0,l=frames.length;j<l;j++) {
        anim.frames.push(frames[j]+fl*count);
      }
      data[anim.name] = anim;
      names.push(anim.name);
    }
  };


  createjs.SpriteSheetUtils = SpriteSheetUtils;
}());

//##############################################################################
// SpriteSheetBuilder.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * The SpriteSheetBuilder allows you to generate sprite sheets at run time from any display object. This can allow
   * you to maintain your assets as vector graphics (for low file size), and render them at run time as sprite sheets
   * for better performance.
   *
   * Sprite sheets can be built either synchronously, or asynchronously, so that large sprite sheets can be generated
   * without locking the UI.
   *
   * Note that the "images" used in the generated sprite sheet are actually canvas elements, and that they will be sized
   * to the nearest power of 2 up to the value of <code>maxWidth</code> or <code>maxHeight</code>.
   * @class SpriteSheetBuilder
   * @extends EventDispatcher
   * @constructor
   **/
  function SpriteSheetBuilder() {
    this.EventDispatcher_constructor();
    
  // public properties:
    /**
     * The maximum width for the images (not individual frames) in the generated sprite sheet. It is recommended to use
     * a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max dimensions, then
     * additional images will be created as needed.
     * @property maxWidth
     * @type Number
     * @default 2048
    */
    this.maxWidth = 2048;
  
    /**
     * The maximum height for the images (not individual frames) in the generated sprite sheet. It is recommended to use
     * a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max dimensions, then
     * additional images will be created as needed.
     * @property maxHeight
     * @type Number
     * @default 2048
     **/
    this.maxHeight = 2048;
  
    /**
     * The sprite sheet that was generated. This will be null before a build is completed successfully.
     * @property spriteSheet
     * @type SpriteSheet
     **/
    this.spriteSheet = null;
  
    /**
     * The scale to apply when drawing all frames to the sprite sheet. This is multiplied against any scale specified
     * in the addFrame call. This can be used, for example, to generate a sprite sheet at run time that is tailored to
     * the a specific device resolution (ex. tablet vs mobile).
     * @property scale
     * @type Number
     * @default 1
     **/
    this.scale = 1;
  
    /**
    * The padding to use between frames. This is helpful to preserve antialiasing on drawn vector content.
    * @property padding
    * @type Number
    * @default 1
    **/
    this.padding = 1;
  
    /**
     * A number from 0.01 to 0.99 that indicates what percentage of time the builder can use. This can be
     * thought of as the number of seconds per second the builder will use. For example, with a timeSlice value of 0.3,
     * the builder will run 20 times per second, using approximately 15ms per build (30% of available time, or 0.3s per second).
     * Defaults to 0.3.
     * @property timeSlice
     * @type Number
     * @default 0.3
     **/
    this.timeSlice = 0.3;
  
    /**
     * A value between 0 and 1 that indicates the progress of a build, or -1 if a build has not
     * been initiated.
     * @property progress
     * @type Number
     * @default -1
     * @readonly
     **/
    this.progress = -1;
  
  
  // private properties:
    /**
     * @property _frames
     * @protected
     * @type Array
     **/
    this._frames = [];
  
    /**
     * @property _animations
     * @protected
     * @type Array
     **/
    this._animations = {};
  
    /**
     * @property _data
     * @protected
     * @type Array
     **/
    this._data = null;
  
    /**
     * @property _nextFrameIndex
     * @protected
     * @type Number
     **/
    this._nextFrameIndex = 0;
  
    /**
     * @property _index
     * @protected
     * @type Number
     **/
    this._index = 0;
  
    /**
     * @property _timerID
     * @protected
     * @type Number
     **/
    this._timerID = null;
  
    /**
     * @property _scale
     * @protected
     * @type Number
     **/
    this._scale = 1;
  }
  var p = createjs.extend(SpriteSheetBuilder, createjs.EventDispatcher);

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// constants:
  SpriteSheetBuilder.ERR_DIMENSIONS = "frame dimensions exceed max spritesheet dimensions";
  SpriteSheetBuilder.ERR_RUNNING = "a build is already running";

// events:
  /**
   * Dispatched when a build completes.
   * @event complete
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @since 0.6.0
   */

  /**
   * Dispatched when an asynchronous build has progress.
   * @event progress
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {Number} progress The current progress value (0-1).
   * @since 0.6.0
   */


// public methods:
  /**
   * Adds a frame to the {{#crossLink "SpriteSheet"}}{{/crossLink}}. Note that the frame will not be drawn until you
   * call {{#crossLink "SpriteSheetBuilder/build"}}{{/crossLink}} method. The optional setup params allow you to have
   * a function run immediately before the draw occurs. For example, this allows you to add a single source multiple
   * times, but manipulate it or its children to change it to generate different frames.
   *
   * Note that the source's transformations (x, y, scale, rotate, alpha) will be ignored, except for regX/Y. To apply
   * transforms to a source object and have them captured in the sprite sheet, simply place it into a {{#crossLink "Container"}}{{/crossLink}}
   * and pass in the Container as the source.
   * @method addFrame
   * @param {DisplayObject} source The source {{#crossLink "DisplayObject"}}{{/crossLink}}  to draw as the frame.
   * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the
   * source to draw to the frame. If not specified, it will look for a <code>getBounds</code> method, bounds property,
   * or <code>nominalBounds</code> property on the source to use. If one is not found, the frame will be skipped.
   * @param {Number} [scale=1] Optional. The scale to draw this frame at. Default is 1.
   * @param {Function} [setupFunction] A function to call immediately before drawing this frame. It will be called with two parameters: the source, and setupData.
   * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter.
   * @return {Number} The index of the frame that was just added, or null if a sourceRect could not be determined.
   **/
  p.addFrame = function(source, sourceRect, scale, setupFunction, setupData) {
    if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
    var rect = sourceRect||source.bounds||source.nominalBounds;
    if (!rect&&source.getBounds) { rect = source.getBounds(); }
    if (!rect) { return null; }
    scale = scale||1;
    return this._frames.push({source:source, sourceRect:rect, scale:scale, funct:setupFunction, data:setupData, index:this._frames.length, height:rect.height*scale})-1;
  };

  /**
   * Adds an animation that will be included in the created sprite sheet.
   * @method addAnimation
   * @param {String} name The name for the animation.
   * @param {Array} frames An array of frame indexes that comprise the animation. Ex. [3,6,5] would describe an animation
   * that played frame indexes 3, 6, and 5 in that order.
   * @param {String} [next] Specifies the name of the animation to continue to after this animation ends. You can
   * also pass false to have the animation stop when it ends. By default it will loop to the start of the same animation.
   * @param {Number} [frequency] Specifies a frame advance frequency for this animation. For example, a value
   * of 2 would cause the animation to advance every second tick.
   **/
  p.addAnimation = function(name, frames, next, frequency) {
    if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
    this._animations[name] = {frames:frames, next:next, frequency:frequency};
  };

  /**
   * This will take a MovieClip instance, and add its frames and labels to this builder. Labels will be added as an animation
   * running from the label index to the next label. For example, if there is a label named "foo" at frame 0 and a label
   * named "bar" at frame 10, in a MovieClip with 15 frames, it will add an animation named "foo" that runs from frame
   * index 0 to 9, and an animation named "bar" that runs from frame index 10 to 14.
   *
   * Note that this will iterate through the full MovieClip with actionsEnabled set to false, ending on the last frame.
   * @method addMovieClip
   * @param {MovieClip} source The source MovieClip instance to add to the sprite sheet.
   * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the source to
   * draw to the frame. If not specified, it will look for a <code>getBounds</code> method, <code>frameBounds</code>
   * Array, <code>bounds</code> property, or <code>nominalBounds</code> property on the source to use. If one is not
   * found, the MovieClip will be skipped.
   * @param {Number} [scale=1] The scale to draw the movie clip at.
   * @param {Function} [setupFunction] A function to call immediately before drawing each frame. It will be called with three parameters: the source, setupData, and the frame index.
   * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter.
   * @param {Function} [labelFunction] This method will be called for each movieclip label that is added with four parameters: the label name, the source movieclip instance, the starting frame index (in the movieclip timeline) and the end index. It must return a new name for the label/animation, or false to exclude the label.
   **/
  p.addMovieClip = function(source, sourceRect, scale, setupFunction, setupData, labelFunction) {
    if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
    var rects = source.frameBounds;
    var rect = sourceRect||source.bounds||source.nominalBounds;
    if (!rect&&source.getBounds) { rect = source.getBounds(); }
    if (!rect && !rects) { return; }

    var i, l, baseFrameIndex = this._frames.length;
    var duration = source.timeline.duration;
    for (i=0; i<duration; i++) {
      var r = (rects&&rects[i]) ? rects[i] : rect;
      this.addFrame(source, r, scale, this._setupMovieClipFrame, {i:i, f:setupFunction, d:setupData});
    }
    var labels = source.timeline._labels;
    var lbls = [];
    for (var n in labels) {
      lbls.push({index:labels[n], label:n});
    }
    if (lbls.length) {
      lbls.sort(function(a,b){ return a.index-b.index; });
      for (i=0,l=lbls.length; i<l; i++) {
        var label = lbls[i].label;
        var start = baseFrameIndex+lbls[i].index;
        var end = baseFrameIndex+((i == l-1) ? duration : lbls[i+1].index);
        var frames = [];
        for (var j=start; j<end; j++) { frames.push(j); }
        if (labelFunction) {
          label = labelFunction(label, source, start, end);
          if (!label) { continue; }
        }
        this.addAnimation(label, frames, true); // for now, this loops all animations.
      }
    }
  };

  /**
   * Builds a SpriteSheet instance based on the current frames.
   * @method build
   * @return {SpriteSheet} The created SpriteSheet instance, or null if a build is already running or an error occurred.
   **/
  p.build = function() {
    if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
    this._startBuild();
    while (this._drawNext()) {}
    this._endBuild();
    return this.spriteSheet;
  };

  /**
   * Asynchronously builds a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance based on the current frames. It will
   * run 20 times per second, using an amount of time defined by <code>timeSlice</code>. When it is complete it will
   * call the specified callback.
   * @method buildAsync
   * @param {Number} [timeSlice] Sets the timeSlice property on this instance.
   **/
  p.buildAsync = function(timeSlice) {
    if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
    this.timeSlice = timeSlice;
    this._startBuild();
    var _this = this;
    this._timerID = setTimeout(function() { _this._run(); }, 50-Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50);
  };

  /**
   * Stops the current asynchronous build.
   * @method stopAsync
   **/
  p.stopAsync = function() {
    clearTimeout(this._timerID);
    this._data = null;
  };

  /**
   * SpriteSheetBuilder instances cannot be cloned.
   * @method clone
   **/
  p.clone = function() {
    throw("SpriteSheetBuilder cannot be cloned.");
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[SpriteSheetBuilder]";
  };


// private methods:
  /**
   * @method _startBuild
   * @protected
   **/
  p._startBuild = function() {
    var pad = this.padding||0;
    this.progress = 0;
    this.spriteSheet = null;
    this._index = 0;
    this._scale = this.scale;
    var dataFrames = [];
    this._data = {
      images: [],
      frames: dataFrames,
      animations: this._animations // TODO: should we "clone" _animations in case someone adds more animations after a build?
    };

    var frames = this._frames.slice();
    frames.sort(function(a,b) { return (a.height<=b.height) ? -1 : 1; });

    if (frames[frames.length-1].height+pad*2 > this.maxHeight) { throw SpriteSheetBuilder.ERR_DIMENSIONS; }
    var y=0, x=0;
    var img = 0;
    while (frames.length) {
      var o = this._fillRow(frames, y, img, dataFrames, pad);
      if (o.w > x) { x = o.w; }
      y += o.h;
      if (!o.h || !frames.length) {
        var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");
        canvas.width = this._getSize(x,this.maxWidth);
        canvas.height = this._getSize(y,this.maxHeight);
        this._data.images[img] = canvas;
        if (!o.h) {
          x=y=0;
          img++;
        }
      }
    }
  };
  
  /**
   * @method _setupMovieClipFrame
   * @protected
   * @return {Number} The width & height of the row.
   **/
  p._setupMovieClipFrame = function(source, data) {
    var ae = source.actionsEnabled;
    source.actionsEnabled = false;
    source.gotoAndStop(data.i);
    source.actionsEnabled = ae;
    data.f&&data.f(source, data.d, data.i);
  };

  /**
   * @method _getSize
   * @protected
   * @return {Number} The width & height of the row.
   **/
  p._getSize = function(size,max) {
    var pow = 4;
    while (Math.pow(2,++pow) < size){}
    return Math.min(max,Math.pow(2,pow));
  };

  /**
   * @method _fillRow
   * @param {Array} frames
   * @param {Number} y
   * @param {HTMLImageElement} img
   * @param {Object} dataFrames
   * @param {Number} pad
   * @protected
   * @return {Number} The width & height of the row.
   **/
  p._fillRow = function(frames, y, img, dataFrames, pad) {
    var w = this.maxWidth;
    var maxH = this.maxHeight;
    y += pad;
    var h = maxH-y;
    var x = pad;
    var height = 0;
    for (var i=frames.length-1; i>=0; i--) {
      var frame = frames[i];
      var sc = this._scale*frame.scale;
      var rect = frame.sourceRect;
      var source = frame.source;
      var rx = Math.floor(sc*rect.x-pad);
      var ry = Math.floor(sc*rect.y-pad);
      var rh = Math.ceil(sc*rect.height+pad*2);
      var rw = Math.ceil(sc*rect.width+pad*2);
      if (rw > w) { throw SpriteSheetBuilder.ERR_DIMENSIONS; }
      if (rh > h || x+rw > w) { continue; }
      frame.img = img;
      frame.rect = new createjs.Rectangle(x,y,rw,rh);
      height = height || rh;
      frames.splice(i,1);
      dataFrames[frame.index] = [x,y,rw,rh,img,Math.round(-rx+sc*source.regX-pad),Math.round(-ry+sc*source.regY-pad)];
      x += rw;
    }
    return {w:x, h:height};
  };

  /**
   * @method _endBuild
   * @protected
   **/
  p._endBuild = function() {
    this.spriteSheet = new createjs.SpriteSheet(this._data);
    this._data = null;
    this.progress = 1;
    this.dispatchEvent("complete");
  };

  /**
   * @method _run
   * @protected
   **/
  p._run = function() {
    var ts = Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50;
    var t = (new Date()).getTime()+ts;
    var complete = false;
    while (t > (new Date()).getTime()) {
      if (!this._drawNext()) { complete = true; break; }
    }
    if (complete) {
      this._endBuild();
    } else {
      var _this = this;
      this._timerID = setTimeout(function() { _this._run(); }, 50-ts);
    }
    var p = this.progress = this._index/this._frames.length;
    if (this.hasEventListener("progress")) {
      var evt = new createjs.Event("progress");
      evt.progress = p;
      this.dispatchEvent(evt);
    }
  };

  /**
   * @method _drawNext
   * @protected
   * @return Boolean Returns false if this is the last draw.
   **/
  p._drawNext = function() {
    var frame = this._frames[this._index];
    var sc = frame.scale*this._scale;
    var rect = frame.rect;
    var sourceRect = frame.sourceRect;
    var canvas = this._data.images[frame.img];
    var ctx = canvas.getContext("2d");
    frame.funct&&frame.funct(frame.source, frame.data);
    ctx.save();
    ctx.beginPath();
    ctx.rect(rect.x, rect.y, rect.width, rect.height);
    ctx.clip();
    ctx.translate(Math.ceil(rect.x-sourceRect.x*sc), Math.ceil(rect.y-sourceRect.y*sc));
    ctx.scale(sc,sc);
    frame.source.draw(ctx); // display object will draw itself.
    ctx.restore();
    return (++this._index) < this._frames.length;
  };


  createjs.SpriteSheetBuilder = createjs.promote(SpriteSheetBuilder, "EventDispatcher");
}());

//##############################################################################
// DOMElement.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * <b>This class is still experimental, and more advanced use is likely to be buggy. Please report bugs.</b>
   *
   * A DOMElement allows you to associate a HTMLElement with the display list. It will be transformed
   * within the DOM as though it is child of the {{#crossLink "Container"}}{{/crossLink}} it is added to. However, it is
   * not rendered to canvas, and as such will retain whatever z-index it has relative to the canvas (ie. it will be
   * drawn in front of or behind the canvas).
   *
   * The position of a DOMElement is relative to their parent node in the DOM. It is recommended that
   * the DOM Object be added to a div that also contains the canvas so that they share the same position
   * on the page.
   *
   * DOMElement is useful for positioning HTML elements over top of canvas content, and for elements
   * that you want to display outside the bounds of the canvas. For example, a tooltip with rich HTML
   * content.
   *
   * <h4>Mouse Interaction</h4>
   *
   * DOMElement instances are not full EaselJS display objects, and do not participate in EaselJS mouse
   * events or support methods like hitTest. To get mouse events from a DOMElement, you must instead add handlers to
   * the htmlElement (note, this does not support EventDispatcher)
   *
   *      var domElement = new createjs.DOMElement(htmlElement);
   *      domElement.htmlElement.onclick = function() {
   *          console.log("clicked");
   *      }
   *
   * @class DOMElement
   * @extends DisplayObject
   * @constructor
   * @param {HTMLElement} htmlElement A reference or id for the DOM element to manage.
   */
  function DOMElement(htmlElement) {
    this.DisplayObject_constructor();
    
    if (typeof(htmlElement)=="string") { htmlElement = document.getElementById(htmlElement); }
    this.mouseEnabled = false;
    
    var style = htmlElement.style;
    style.position = "absolute";
    style.transformOrigin = style.WebkitTransformOrigin = style.msTransformOrigin = style.MozTransformOrigin = style.OTransformOrigin = "0% 0%";
    
    
  // public properties:
    /**
     * The DOM object to manage.
     * @property htmlElement
     * @type HTMLElement
     */
    this.htmlElement = htmlElement;
  
  
  // private properties:
    /**
     * @property _oldMtx
     * @type Matrix2D
     * @protected
     */
    this._oldProps = null;
  }
  var p = createjs.extend(DOMElement, createjs.DisplayObject);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// public methods:
  /**
   * Returns true or false indicating whether the display object would be visible if drawn to a canvas.
   * This does not account for whether it would be visible within the boundaries of the stage.
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method isVisible
   * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
   */
  p.isVisible = function() {
    return this.htmlElement != null;
  };

  /**
   * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
   * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
   * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
   * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
   * into itself).
   * @return {Boolean}
   */
  p.draw = function(ctx, ignoreCache) {
    // this relies on the _tick method because draw isn't called if the parent is not visible.
    // the actual update happens in _handleDrawEnd
    return true;
  };

  /**
   * Not applicable to DOMElement.
   * @method cache
   */
  p.cache = function() {};

  /**
   * Not applicable to DOMElement.
   * @method uncache
   */
  p.uncache = function() {};

  /**
   * Not applicable to DOMElement.
   * @method updateCache
   */
  p.updateCache = function() {};

  /**
   * Not applicable to DOMElement.
   * @method hitTest
   */
  p.hitTest = function() {};

  /**
   * Not applicable to DOMElement.
   * @method localToGlobal
   */
  p.localToGlobal = function() {};

  /**
   * Not applicable to DOMElement.
   * @method globalToLocal
   */
  p.globalToLocal = function() {};

  /**
   * Not applicable to DOMElement.
   * @method localToLocal
   */
  p.localToLocal = function() {};

  /**
   * DOMElement cannot be cloned. Throws an error.
   * @method clone
   */
  p.clone = function() {
    throw("DOMElement cannot be cloned.")
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   */
  p.toString = function() {
    return "[DOMElement (name="+  this.name +")]";
  };

  /**
     * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
   * are not full EaselJS display objects and do not participate in EaselJS mouse events.
   * @event click
   */

     /**
     * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
   * are not full EaselJS display objects and do not participate in EaselJS mouse events.
   * @event dblClick
   */

     /**
      * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
    * are not full EaselJS display objects and do not participate in EaselJS mouse events.
    * @event mousedown
    */

     /**
      * The HTMLElement can listen for the mouseover event, not the DOMElement instance.
      * Since DOMElement instances are not full EaselJS display objects and do not participate in EaselJS mouse events.
      * @event mouseover
    */

     /**
      * Not applicable to DOMElement.
    * @event tick
    */


// private methods:
  /**
   * @method _tick
   * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs.
   * function.
   * @protected
   */
  p._tick = function(evtObj) {
    var stage = this.getStage();
    stage&&stage.on("drawend", this._handleDrawEnd, this, true);
    this.DisplayObject__tick(evtObj);
  };
  
  /**
   * @method _handleDrawEnd
   * @param {Event} evt
   * @protected
   */
  p._handleDrawEnd = function(evt) {
    var o = this.htmlElement;
    if (!o) { return; }
    var style = o.style;
    
    var props = this.getConcatenatedDisplayProps(this._props), mtx = props.matrix;
    
    var visibility = props.visible ? "visible" : "hidden";
    if (visibility != style.visibility) { style.visibility = visibility; }
    if (!props.visible) { return; }
    
    var oldProps = this._oldProps, oldMtx = oldProps&&oldProps.matrix;
    var n = 10000; // precision
    
    if (!oldMtx || !oldMtx.equals(mtx)) {
      var str = "matrix(" + (mtx.a*n|0)/n +","+ (mtx.b*n|0)/n +","+ (mtx.c*n|0)/n +","+ (mtx.d*n|0)/n +","+ (mtx.tx+0.5|0);
      style.transform = style.WebkitTransform = style.OTransform = style.msTransform = str +","+ (mtx.ty+0.5|0) +")";
      style.MozTransform = str +"px,"+ (mtx.ty+0.5|0) +"px)";
      if (!oldProps) { oldProps = this._oldProps = new createjs.DisplayProps(true, NaN); }
      oldProps.matrix.copy(mtx);
    }
    
    if (oldProps.alpha != props.alpha) {
      style.opacity = ""+(props.alpha*n|0)/n;
      oldProps.alpha = props.alpha;
    }
  };


  createjs.DOMElement = createjs.promote(DOMElement, "DisplayObject");
}());

//##############################################################################
// Filter.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Base class that all filters should inherit from. Filters need to be applied to objects that have been cached using
   * the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method. If an object changes, please cache it again, or use
   * {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}. Note that the filters must be applied before caching.
   *
   * <h4>Example</h4>
   *
   *      myInstance.filters = [
   *          new createjs.ColorFilter(0, 0, 0, 1, 255, 0, 0),
   *          new createjs.BlurFilter(5, 5, 10)
   *      ];
   *      myInstance.cache(0,0, 100, 100);
   *
   * Note that each filter can implement a {{#crossLink "Filter/getBounds"}}{{/crossLink}} method, which returns the
   * margins that need to be applied in order to fully display the filter. For example, the {{#crossLink "BlurFilter"}}{{/crossLink}}
   * will cause an object to feather outwards, resulting in a margin around the shape.
   *
   * <h4>EaselJS Filters</h4>
   * EaselJS comes with a number of pre-built filters. Note that individual filters are not compiled into the minified
   * version of EaselJS. To use them, you must include them manually in the HTML.
   * <ul><li>{{#crossLink "AlphaMapFilter"}}{{/crossLink}} : Map a greyscale image to the alpha channel of a display object</li>
   *      <li>{{#crossLink "AlphaMaskFilter"}}{{/crossLink}}: Map an image's alpha channel to the alpha channel of a display object</li>
   *      <li>{{#crossLink "BlurFilter"}}{{/crossLink}}: Apply vertical and horizontal blur to a display object</li>
   *      <li>{{#crossLink "ColorFilter"}}{{/crossLink}}: Color transform a display object</li>
   *      <li>{{#crossLink "ColorMatrixFilter"}}{{/crossLink}}: Transform an image using a {{#crossLink "ColorMatrix"}}{{/crossLink}}</li>
   * </ul>
   *
   * @class Filter
   * @constructor
   **/
  function Filter() {}
  var p = Filter.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// public methods:
  /**
   * Provides padding values for this filter. That is, how much the filter will extend the visual bounds of an object it is applied to.
   * @method getBounds
   * @param {Rectangle} [rect] If specified, the provided Rectangle instance will be expanded by the padding amounts and returned.
   * @return {Rectangle} If a `rect` param was provided, it is returned. If not, either a new rectangle with the padding values, or null if no padding is required for this filter.
   **/
  p.getBounds = function(rect) {
    return rect;
  };

  /**
   * Applies the filter to the specified context.
   * @method applyFilter
   * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source.
   * @param {Number} x The x position to use for the source rect.
   * @param {Number} y The y position to use for the source rect.
   * @param {Number} width The width to use for the source rect.
   * @param {Number} height The height to use for the source rect.
   * @param {CanvasRenderingContext2D} [targetCtx] The 2D context to draw the result to. Defaults to the context passed to ctx.
   * @param {Number} [targetX] The x position to draw the result to. Defaults to the value passed to x.
   * @param {Number} [targetY] The y position to draw the result to. Defaults to the value passed to y.
   * @return {Boolean} If the filter was applied successfully.
   **/
  p.applyFilter = function(ctx, x, y, width, height, targetCtx, targetX, targetY) {
    // this is the default behaviour because most filters access pixel data. It is overridden when not needed.
    targetCtx = targetCtx || ctx;
    if (targetX == null) { targetX = x; }
    if (targetY == null) { targetY = y; }
    try {
      var imageData = ctx.getImageData(x, y, width, height);
    } catch (e) {
      return false;
    }
    if (this._applyFilter(imageData)) {
      targetCtx.putImageData(imageData, targetX, targetY);
      return true;
    }
    return false;
  };

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[Filter]";
  };

  /**
   * Returns a clone of this Filter instance.
   * @method clone
   * @return {Filter} A clone of the current Filter instance.
   **/
  p.clone = function() {
    return new Filter();
  };
  
// private methods:
  /**
   * @method _applyFilter
   * @param {ImageData} imageData Target ImageData instance.
   * @return {Boolean}
   **/
  p._applyFilter = function(imageData) { return true; };


  createjs.Filter = Filter;
}());

//##############################################################################
// BlurFilter.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Applies a box blur to DisplayObjects. Note that this filter is fairly CPU intensive, particularly if the quality is
   * set higher than 1.
   *
   * <h4>Example</h4>
   * This example creates a red circle, and then applies a 5 pixel blur to it. It uses the {{#crossLink "Filter/getBounds"}}{{/crossLink}}
   * method to account for the spread that the blur causes.
   *
   *      var shape = new createjs.Shape().set({x:100,y:100});
   *      shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
   *
   *      var blurFilter = new createjs.BlurFilter(5, 5, 1);
   *      shape.filters = [blurFilter];
   *      var bounds = blurFilter.getBounds();
   *
   *      shape.cache(-50+bounds.x, -50+bounds.y, 100+bounds.width, 100+bounds.height);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
   * @class BlurFilter
   * @extends Filter
   * @constructor
   * @param {Number} [blurX=0] The horizontal blur radius in pixels.
   * @param {Number} [blurY=0] The vertical blur radius in pixels.
   * @param {Number} [quality=1] The number of blur iterations.
   **/
  function BlurFilter( blurX, blurY, quality) {
    if ( isNaN(blurX) || blurX < 0 ) blurX = 0;
    if ( isNaN(blurY) || blurY < 0 ) blurY = 0;
    if ( isNaN(quality) || quality < 1  ) quality = 1;


    // public properties:
    /**
     * Horizontal blur radius in pixels
     * @property blurX
     * @default 0
     * @type Number
     **/
    this.blurX = blurX | 0;

    /**
     * Vertical blur radius in pixels
     * @property blurY
     * @default 0
     * @type Number
     **/
    this.blurY = blurY | 0;

    /**
     * Number of blur iterations. For example, a value of 1 will produce a rough blur. A value of 2 will produce a
     * smoother blur, but take twice as long to run.
     * @property quality
     * @default 1
     * @type Number
     **/
    this.quality = quality | 0;
  }
  var p = createjs.extend(BlurFilter, createjs.Filter);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// constants:
  /**
   * Array of multiply values for blur calculations.
   * @property MUL_TABLE
   * @type Array
   * @protected
   * @static
   **/
  BlurFilter.MUL_TABLE = [1, 171, 205, 293, 57, 373, 79, 137, 241, 27, 391, 357, 41, 19, 283, 265, 497, 469, 443, 421, 25, 191, 365, 349, 335, 161, 155, 149, 9, 278, 269, 261, 505, 245, 475, 231, 449, 437, 213, 415, 405, 395, 193, 377, 369, 361, 353, 345, 169, 331, 325, 319, 313, 307, 301, 37, 145, 285, 281, 69, 271, 267, 263, 259, 509, 501, 493, 243, 479, 118, 465, 459, 113, 446, 55, 435, 429, 423, 209, 413, 51, 403, 199, 393, 97, 3, 379, 375, 371, 367, 363, 359, 355, 351, 347, 43, 85, 337, 333, 165, 327, 323, 5, 317, 157, 311, 77, 305, 303, 75, 297, 294, 73, 289, 287, 71, 141, 279, 277, 275, 68, 135, 67, 133, 33, 262, 260, 129, 511, 507, 503, 499, 495, 491, 61, 121, 481, 477, 237, 235, 467, 232, 115, 457, 227, 451, 7, 445, 221, 439, 218, 433, 215, 427, 425, 211, 419, 417, 207, 411, 409, 203, 202, 401, 399, 396, 197, 49, 389, 387, 385, 383, 95, 189, 47, 187, 93, 185, 23, 183, 91, 181, 45, 179, 89, 177, 11, 175, 87, 173, 345, 343, 341, 339, 337, 21, 167, 83, 331, 329, 327, 163, 81, 323, 321, 319, 159, 79, 315, 313, 39, 155, 309, 307, 153, 305, 303, 151, 75, 299, 149, 37, 295, 147, 73, 291, 145, 289, 287, 143, 285, 71, 141, 281, 35, 279, 139, 69, 275, 137, 273, 17, 271, 135, 269, 267, 133, 265, 33, 263, 131, 261, 130, 259, 129, 257, 1];

  /**
   * Array of shift values for blur calculations.
   * @property SHG_TABLE
   * @type Array
   * @protected
   * @static
   **/
  BlurFilter.SHG_TABLE = [0, 9, 10, 11, 9, 12, 10, 11, 12, 9, 13, 13, 10, 9, 13, 13, 14, 14, 14, 14, 10, 13, 14, 14, 14, 13, 13, 13, 9, 14, 14, 14, 15, 14, 15, 14, 15, 15, 14, 15, 15, 15, 14, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 12, 14, 15, 15, 13, 15, 15, 15, 15, 16, 16, 16, 15, 16, 14, 16, 16, 14, 16, 13, 16, 16, 16, 15, 16, 13, 16, 15, 16, 14, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 14, 16, 16, 15, 16, 16, 10, 16, 15, 16, 14, 16, 16, 14, 16, 16, 14, 16, 16, 14, 15, 16, 16, 16, 14, 15, 14, 15, 13, 16, 16, 15, 17, 17, 17, 17, 17, 17, 14, 15, 17, 17, 16, 16, 17, 16, 15, 17, 16, 17, 11, 17, 16, 17, 16, 17, 16, 17, 17, 16, 17, 17, 16, 17, 17, 16, 16, 17, 17, 17, 16, 14, 17, 17, 17, 17, 15, 16, 14, 16, 15, 16, 13, 16, 15, 16, 14, 16, 15, 16, 12, 16, 15, 16, 17, 17, 17, 17, 17, 13, 16, 15, 17, 17, 17, 16, 15, 17, 17, 17, 16, 15, 17, 17, 14, 16, 17, 17, 16, 17, 17, 16, 15, 17, 16, 14, 17, 16, 15, 17, 16, 17, 17, 16, 17, 15, 16, 17, 14, 17, 16, 15, 17, 16, 17, 13, 17, 16, 17, 17, 16, 17, 14, 17, 16, 17, 16, 17, 16, 17, 9];

// public methods:
  /** docced in super class **/
  p.getBounds = function (rect) {
    var x = this.blurX|0, y = this.blurY| 0;
    if (x <= 0 && y <= 0) { return rect; }
    var q = Math.pow(this.quality, 0.2);
    return (rect || new createjs.Rectangle()).pad(x*q+1,y*q+1,x*q+1,y*q+1);
  };

  /** docced in super class **/
  p.clone = function() {
    return new BlurFilter(this.blurX, this.blurY, this.quality);
  };

  /** docced in super class **/
  p.toString = function() {
    return "[BlurFilter]";
  };


// private methods:

  /** docced in super class **/
  p._applyFilter = function (imageData) {

    var radiusX = this.blurX >> 1;
    if (isNaN(radiusX) || radiusX < 0) return false;
    var radiusY = this.blurY >> 1;
    if (isNaN(radiusY) || radiusY < 0) return false;
    if (radiusX == 0 && radiusY == 0) return false;

    var iterations = this.quality;
    if (isNaN(iterations) || iterations < 1) iterations = 1;
    iterations |= 0;
    if (iterations > 3) iterations = 3;
    if (iterations < 1) iterations = 1;

    var px = imageData.data;
    var x=0, y=0, i=0, p=0, yp=0, yi=0, yw=0, r=0, g=0, b=0, a=0, pr=0, pg=0, pb=0, pa=0;

    var divx = (radiusX + radiusX + 1) | 0;
    var divy = (radiusY + radiusY + 1) | 0;
    var w = imageData.width | 0;
    var h = imageData.height | 0;

    var w1 = (w - 1) | 0;
    var h1 = (h - 1) | 0;
    var rxp1 = (radiusX + 1) | 0;
    var ryp1 = (radiusY + 1) | 0;

    var ssx = {r:0,b:0,g:0,a:0};
    var sx = ssx;
    for ( i = 1; i < divx; i++ )
    {
      sx = sx.n = {r:0,b:0,g:0,a:0};
    }
    sx.n = ssx;

    var ssy = {r:0,b:0,g:0,a:0};
    var sy = ssy;
    for ( i = 1; i < divy; i++ )
    {
      sy = sy.n = {r:0,b:0,g:0,a:0};
    }
    sy.n = ssy;

    var si = null;


    var mtx = BlurFilter.MUL_TABLE[radiusX] | 0;
    var stx = BlurFilter.SHG_TABLE[radiusX] | 0;
    var mty = BlurFilter.MUL_TABLE[radiusY] | 0;
    var sty = BlurFilter.SHG_TABLE[radiusY] | 0;

    while (iterations-- > 0) {

      yw = yi = 0;
      var ms = mtx;
      var ss = stx;
      for (y = h; --y > -1;) {
        r = rxp1 * (pr = px[(yi) | 0]);
        g = rxp1 * (pg = px[(yi + 1) | 0]);
        b = rxp1 * (pb = px[(yi + 2) | 0]);
        a = rxp1 * (pa = px[(yi + 3) | 0]);

        sx = ssx;

        for( i = rxp1; --i > -1; )
        {
          sx.r = pr;
          sx.g = pg;
          sx.b = pb;
          sx.a = pa;
          sx = sx.n;
        }

        for( i = 1; i < rxp1; i++ )
        {
          p = (yi + ((w1 < i ? w1 : i) << 2)) | 0;
          r += ( sx.r = px[p]);
          g += ( sx.g = px[p+1]);
          b += ( sx.b = px[p+2]);
          a += ( sx.a = px[p+3]);

          sx = sx.n;
        }

        si = ssx;
        for ( x = 0; x < w; x++ )
        {
          px[yi++] = (r * ms) >>> ss;
          px[yi++] = (g * ms) >>> ss;
          px[yi++] = (b * ms) >>> ss;
          px[yi++] = (a * ms) >>> ss;

          p = ((yw + ((p = x + radiusX + 1) < w1 ? p : w1)) << 2);

          r -= si.r - ( si.r = px[p]);
          g -= si.g - ( si.g = px[p+1]);
          b -= si.b - ( si.b = px[p+2]);
          a -= si.a - ( si.a = px[p+3]);

          si = si.n;

        }
        yw += w;
      }

      ms = mty;
      ss = sty;
      for (x = 0; x < w; x++) {
        yi = (x << 2) | 0;

        r = (ryp1 * (pr = px[yi])) | 0;
        g = (ryp1 * (pg = px[(yi + 1) | 0])) | 0;
        b = (ryp1 * (pb = px[(yi + 2) | 0])) | 0;
        a = (ryp1 * (pa = px[(yi + 3) | 0])) | 0;

        sy = ssy;
        for( i = 0; i < ryp1; i++ )
        {
          sy.r = pr;
          sy.g = pg;
          sy.b = pb;
          sy.a = pa;
          sy = sy.n;
        }

        yp = w;

        for( i = 1; i <= radiusY; i++ )
        {
          yi = ( yp + x ) << 2;

          r += ( sy.r = px[yi]);
          g += ( sy.g = px[yi+1]);
          b += ( sy.b = px[yi+2]);
          a += ( sy.a = px[yi+3]);

          sy = sy.n;

          if( i < h1 )
          {
            yp += w;
          }
        }

        yi = x;
        si = ssy;
        if ( iterations > 0 )
        {
          for ( y = 0; y < h; y++ )
          {
            p = yi << 2;
            px[p+3] = pa =(a * ms) >>> ss;
            if ( pa > 0 )
            {
              px[p]   = ((r * ms) >>> ss );
              px[p+1] = ((g * ms) >>> ss );
              px[p+2] = ((b * ms) >>> ss );
            } else {
              px[p] = px[p+1] = px[p+2] = 0
            }

            p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2;

            r -= si.r - ( si.r = px[p]);
            g -= si.g - ( si.g = px[p+1]);
            b -= si.b - ( si.b = px[p+2]);
            a -= si.a - ( si.a = px[p+3]);

            si = si.n;

            yi += w;
          }
        } else {
          for ( y = 0; y < h; y++ )
          {
            p = yi << 2;
            px[p+3] = pa =(a * ms) >>> ss;
            if ( pa > 0 )
            {
              pa = 255 / pa;
              px[p]   = ((r * ms) >>> ss ) * pa;
              px[p+1] = ((g * ms) >>> ss ) * pa;
              px[p+2] = ((b * ms) >>> ss ) * pa;
            } else {
              px[p] = px[p+1] = px[p+2] = 0
            }

            p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2;

            r -= si.r - ( si.r = px[p]);
            g -= si.g - ( si.g = px[p+1]);
            b -= si.b - ( si.b = px[p+2]);
            a -= si.a - ( si.a = px[p+3]);

            si = si.n;

            yi += w;
          }
        }
      }

    }
    return true;
  };

  createjs.BlurFilter = createjs.promote(BlurFilter, "Filter");
}());

//##############################################################################
// AlphaMapFilter.js
//##############################################################################

(function () {
  "use strict";
  
  
// constructor:
  /**
   * Applies a greyscale alpha map image (or canvas) to the target, such that the alpha channel of the result will
   * be copied from the red channel of the map, and the RGB channels will be copied from the target.
   *
   * Generally, it is recommended that you use {{#crossLink "AlphaMaskFilter"}}{{/crossLink}}, because it has much
   * better performance.
   *
   * <h4>Example</h4>
   * This example draws a red->blue box, caches it, and then uses the cache canvas as an alpha map on a 100x100 image.
   *
   *       var box = new createjs.Shape();
   *       box.graphics.beginLinearGradientFill(["#ff0000", "#0000ff"], [0, 1], 0, 0, 0, 100)
   *       box.graphics.drawRect(0, 0, 100, 100);
   *       box.cache(0, 0, 100, 100);
   *
   *       var bmp = new createjs.Bitmap("path/to/image.jpg");
   *       bmp.filters = [
   *           new createjs.AlphaMapFilter(box.cacheCanvas)
   *       ];
   *       bmp.cache(0, 0, 100, 100);
   *       stage.addChild(bmp);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters.
   * @class AlphaMapFilter
   * @extends Filter
   * @constructor
   * @param {HTMLImageElement|HTMLCanvasElement} alphaMap The greyscale image (or canvas) to use as the alpha value for the
   * result. This should be exactly the same dimensions as the target.
   **/
  function AlphaMapFilter(alphaMap) {
  
  
  // public properties:
    /**
     * The greyscale image (or canvas) to use as the alpha value for the result. This should be exactly the same
     * dimensions as the target.
     * @property alphaMap
     * @type HTMLImageElement|HTMLCanvasElement
     **/
    this.alphaMap = alphaMap;
    
    
  // private properties:
    /**
     * @property _alphaMap
     * @protected
     * @type HTMLImageElement|HTMLCanvasElement
     **/
    this._alphaMap = null;
    
    /**
     * @property _mapData
     * @protected
     * @type Uint8ClampedArray
     **/
    this._mapData = null;
  }
  var p = createjs.extend(AlphaMapFilter, createjs.Filter);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// public methods:
  /** docced in super class **/
  p.clone = function () {
    var o = new AlphaMapFilter(this.alphaMap);
    o._alphaMap = this._alphaMap;
    o._mapData = this._mapData;
    return o;
  };

  /** docced in super class **/
  p.toString = function () {
    return "[AlphaMapFilter]";
  };


// private methods:
  /** docced in super class **/
  p._applyFilter = function (imageData) {
    if (!this.alphaMap) { return true; }
    if (!this._prepAlphaMap()) { return false; }
    
    // TODO: update to support scenarios where the target has different dimensions.
    var data = imageData.data;
    var map = this._mapData;
    for(var i=0, l=data.length; i<l; i += 4) { data[i + 3] = map[i] || 0; }
    
    return true;
  };

  /**
   * @method _prepAlphaMap
   * @protected
   **/
  p._prepAlphaMap = function () {
    if (!this.alphaMap) { return false; }
    if (this.alphaMap == this._alphaMap && this._mapData) { return true; }

    this._mapData = null;
    var map = this._alphaMap = this.alphaMap;
    var canvas = map;
    var ctx;
    if (map instanceof HTMLCanvasElement) {
      ctx = canvas.getContext("2d");
    } else {
      canvas = createjs.createCanvas ? createjs.createCanvas() : document.createElement("canvas");
      canvas.width = map.width;
      canvas.height = map.height;
      ctx = canvas.getContext("2d");
      ctx.drawImage(map, 0, 0);
    }

    try {
      var imgData = ctx.getImageData(0, 0, map.width, map.height);
    } catch (e) {
      //if (!this.suppressCrossDomainErrors) throw new Error("unable to access local image data: " + e);
      return false;
    }
    
    this._mapData = imgData.data;
    return true;
  };


  createjs.AlphaMapFilter = createjs.promote(AlphaMapFilter, "Filter");
}());

//##############################################################################
// AlphaMaskFilter.js
//##############################################################################

(function () {
  "use strict";


// constructor:
  /**
   * Applies the alpha from the mask image (or canvas) to the target, such that the alpha channel of the result will
   * be derived from the mask, and the RGB channels will be copied from the target. This can be used, for example, to
   * apply an alpha mask to a display object. This can also be used to combine a JPG compressed RGB image with a PNG32
   * alpha mask, which can result in a much smaller file size than a single PNG32 containing ARGB.
   *
   * <b>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters correctly.</b>
   *
   * <h4>Example</h4>
   * This example draws a gradient box, then caches it and uses the "cacheCanvas" as the alpha mask on a 100x100 image.
   *
   *      var box = new createjs.Shape();
   *      box.graphics.beginLinearGradientFill(["#000000", "rgba(0, 0, 0, 0)"], [0, 1], 0, 0, 100, 100)
   *      box.graphics.drawRect(0, 0, 100, 100);
   *      box.cache(0, 0, 100, 100);
   *
   *      var bmp = new createjs.Bitmap("path/to/image.jpg");
   *      bmp.filters = [
   *          new createjs.AlphaMaskFilter(box.cacheCanvas)
   *      ];
   *      bmp.cache(0, 0, 100, 100);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters.
   * @class AlphaMaskFilter
   * @extends Filter
   * @constructor
   * @param {HTMLImageElement|HTMLCanvasElement} mask
   **/
  function AlphaMaskFilter(mask) {
  
  
  // public properties:
    /**
     * The image (or canvas) to use as the mask.
     * @property mask
     * @type HTMLImageElement|HTMLCanvasElement
     **/
    this.mask = mask;
  }
  var p = createjs.extend(AlphaMaskFilter, createjs.Filter);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
  

// public methods:
  /**
   * Applies the filter to the specified context.
   *
   * <strong>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters
   * correctly.</strong>
   * @method applyFilter
   * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source.
   * @param {Number} x The x position to use for the source rect.
   * @param {Number} y The y position to use for the source rect.
   * @param {Number} width The width to use for the source rect.
   * @param {Number} height The height to use for the source rect.
   * @param {CanvasRenderingContext2D} [targetCtx] NOT SUPPORTED IN THIS FILTER. The 2D context to draw the result to. Defaults to the context passed to ctx.
   * @param {Number} [targetX] NOT SUPPORTED IN THIS FILTER. The x position to draw the result to. Defaults to the value passed to x.
   * @param {Number} [targetY] NOT SUPPORTED IN THIS FILTER. The y position to draw the result to. Defaults to the value passed to y.
   * @return {Boolean} If the filter was applied successfully.
   **/
  p.applyFilter = function (ctx, x, y, width, height, targetCtx, targetX, targetY) {
    if (!this.mask) { return true; }
    targetCtx = targetCtx || ctx;
    if (targetX == null) { targetX = x; }
    if (targetY == null) { targetY = y; }

    targetCtx.save();
    if (ctx != targetCtx) {
      // TODO: support targetCtx and targetX/Y
      // clearRect, then draw the ctx in?
      return false;
    }

    targetCtx.globalCompositeOperation = "destination-in";
    targetCtx.drawImage(this.mask, targetX, targetY);
    targetCtx.restore();
    return true;
  };

  /** docced in super class **/
  p.clone = function () {
    return new AlphaMaskFilter(this.mask);
  };

  /** docced in super class **/
  p.toString = function () {
    return "[AlphaMaskFilter]";
  };


  createjs.AlphaMaskFilter = createjs.promote(AlphaMaskFilter, "Filter");
}());

//##############################################################################
// ColorFilter.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Applies a color transform to DisplayObjects.
   *
   * <h4>Example</h4>
   * This example draws a red circle, and then transforms it to Blue. This is accomplished by multiplying all the channels
   * to 0 (except alpha, which is set to 1), and then adding 255 to the blue channel.
   *
   *      var shape = new createjs.Shape().set({x:100,y:100});
   *      shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
   *
   *      shape.filters = [
   *          new createjs.ColorFilter(0,0,0,1, 0,0,255,0)
   *      ];
   *      shape.cache(-50, -50, 100, 100);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
   * @class ColorFilter
   * @param {Number} [redMultiplier=1] The amount to multiply against the red channel. This is a range between 0 and 1.
   * @param {Number} [greenMultiplier=1] The amount to multiply against the green channel. This is a range between 0 and 1.
   * @param {Number} [blueMultiplier=1] The amount to multiply against the blue channel. This is a range between 0 and 1.
   * @param {Number} [alphaMultiplier=1] The amount to multiply against the alpha channel. This is a range between 0 and 1.
   * @param {Number} [redOffset=0] The amount to add to the red channel after it has been multiplied. This is a range
   * between -255 and 255.
   * @param {Number} [greenOffset=0] The amount to add to the green channel after it has been multiplied. This is a range
    * between -255 and 255.
   * @param {Number} [blueOffset=0] The amount to add to the blue channel after it has been multiplied. This is a range
    * between -255 and 255.
   * @param {Number} [alphaOffset=0] The amount to add to the alpha channel after it has been multiplied. This is a range
    * between -255 and 255.
   * @constructor
   * @extends Filter
   **/
  function ColorFilter(redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier, redOffset, greenOffset, blueOffset, alphaOffset) {
    
  
  // public properties:
    /**
     * Red channel multiplier.
     * @property redMultiplier
     * @type Number
     **/
    this.redMultiplier = redMultiplier != null ? redMultiplier : 1;
  
    /**
     * Green channel multiplier.
     * @property greenMultiplier
     * @type Number
     **/
    this.greenMultiplier = greenMultiplier != null ? greenMultiplier : 1;
  
    /**
     * Blue channel multiplier.
     * @property blueMultiplier
     * @type Number
     **/
    this.blueMultiplier = blueMultiplier != null ? blueMultiplier : 1;
  
    /**
     * Alpha channel multiplier.
     * @property alphaMultiplier
     * @type Number
     **/
    this.alphaMultiplier = alphaMultiplier != null ? alphaMultiplier : 1;
  
    /**
     * Red channel offset (added to value).
     * @property redOffset
     * @type Number
     **/
    this.redOffset = redOffset || 0;
  
    /**
     * Green channel offset (added to value).
     * @property greenOffset
     * @type Number
     **/
    this.greenOffset = greenOffset || 0;
  
    /**
     * Blue channel offset (added to value).
     * @property blueOffset
     * @type Number
     **/
    this.blueOffset = blueOffset || 0;
  
    /**
     * Alpha channel offset (added to value).
     * @property alphaOffset
     * @type Number
     **/
    this.alphaOffset = alphaOffset || 0;
  }
  var p = createjs.extend(ColorFilter, createjs.Filter);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// public methods:
  /** docced in super class **/
  p.toString = function() {
    return "[ColorFilter]";
  };

  /** docced in super class **/
  p.clone = function() {
    return new ColorFilter(this.redMultiplier, this.greenMultiplier, this.blueMultiplier, this.alphaMultiplier, this.redOffset, this.greenOffset, this.blueOffset, this.alphaOffset);
  };
  

// private methods:
  /** docced in super class **/
  p._applyFilter = function(imageData) {
    var data = imageData.data;
    var l = data.length;
    for (var i=0; i<l; i+=4) {
      data[i] = data[i]*this.redMultiplier+this.redOffset;
      data[i+1] = data[i+1]*this.greenMultiplier+this.greenOffset;
      data[i+2] = data[i+2]*this.blueMultiplier+this.blueOffset;
      data[i+3] = data[i+3]*this.alphaMultiplier+this.alphaOffset;
    }
    return true;
  };


  createjs.ColorFilter = createjs.promote(ColorFilter, "Filter");
}());

//##############################################################################
// ColorMatrix.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Provides helper functions for assembling a matrix for use with the {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}.
   * Most methods return the instance to facilitate chained calls.
   *
   * <h4>Example</h4>
   *
   *      myColorMatrix.adjustHue(20).adjustBrightness(50);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for an example of how to apply filters, or {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}
   * for an example of how to use ColorMatrix to change a DisplayObject's color.
   * @class ColorMatrix
   * @param {Number} brightness
   * @param {Number} contrast
   * @param {Number} saturation
   * @param {Number} hue
   * @constructor
   **/
  function ColorMatrix(brightness, contrast, saturation, hue) {
    this.setColor(brightness, contrast, saturation, hue);
  }
  var p = ColorMatrix.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// constants:
  /**
   * Array of delta values for contrast calculations.
   * @property DELTA_INDEX
   * @type Array
   * @protected
   * @static
   **/
  ColorMatrix.DELTA_INDEX = [
    0,    0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1,  0.11,
    0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
    0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
    0.44, 0.46, 0.48, 0.5,  0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
    0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
    1.0,  1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
    1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0,  2.12, 2.25,
    2.37, 2.50, 2.62, 2.75, 2.87, 3.0,  3.2,  3.4,  3.6,  3.8,
    4.0,  4.3,  4.7,  4.9,  5.0,  5.5,  6.0,  6.5,  6.8,  7.0,
    7.3,  7.5,  7.8,  8.0,  8.4,  8.7,  9.0,  9.4,  9.6,  9.8,
    10.0
  ];

  /**
   * Identity matrix values.
   * @property IDENTITY_MATRIX
   * @type Array
   * @protected
   * @static
   **/
  ColorMatrix.IDENTITY_MATRIX = [
    1,0,0,0,0,
    0,1,0,0,0,
    0,0,1,0,0,
    0,0,0,1,0,
    0,0,0,0,1
  ];

  /**
   * The constant length of a color matrix.
   * @property LENGTH
   * @type Number
   * @protected
   * @static
   **/
  ColorMatrix.LENGTH = ColorMatrix.IDENTITY_MATRIX.length;


// public methods:
  /**
   * Resets the instance with the specified values.
   * @method setColor
   * @param {Number} brightness
   * @param {Number} contrast
   * @param {Number} saturation
   * @param {Number} hue
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   */
  p.setColor = function(brightness,contrast,saturation,hue) {
    return this.reset().adjustColor(brightness,contrast,saturation,hue);
  };

  /**
   * Resets the matrix to identity values.
   * @method reset
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   */
  p.reset = function() {
    return this.copy(ColorMatrix.IDENTITY_MATRIX);
  };

  /**
   * Shortcut method to adjust brightness, contrast, saturation and hue.
   * Equivalent to calling adjustHue(hue), adjustContrast(contrast),
   * adjustBrightness(brightness), adjustSaturation(saturation), in that order.
   * @method adjustColor
   * @param {Number} brightness
   * @param {Number} contrast
   * @param {Number} saturation
   * @param {Number} hue
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.adjustColor = function(brightness,contrast,saturation,hue) {
    this.adjustHue(hue);
    this.adjustContrast(contrast);
    this.adjustBrightness(brightness);
    return this.adjustSaturation(saturation);
  };

  /**
   * Adjusts the brightness of pixel color by adding the specified value to the red, green and blue channels.
   * Positive values will make the image brighter, negative values will make it darker.
   * @method adjustBrightness
   * @param {Number} value A value between -255 & 255 that will be added to the RGB channels.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.adjustBrightness = function(value) {
    if (value == 0 || isNaN(value)) { return this; }
    value = this._cleanValue(value,255);
    this._multiplyMatrix([
      1,0,0,0,value,
      0,1,0,0,value,
      0,0,1,0,value,
      0,0,0,1,0,
      0,0,0,0,1
    ]);
    return this;
  };

  /**
   * Adjusts the contrast of pixel color.
   * Positive values will increase contrast, negative values will decrease contrast.
   * @method adjustContrast
   * @param {Number} value A value between -100 & 100.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.adjustContrast = function(value) {
    if (value == 0 || isNaN(value)) { return this; }
    value = this._cleanValue(value,100);
    var x;
    if (value<0) {
      x = 127+value/100*127;
    } else {
      x = value%1;
      if (x == 0) {
        x = ColorMatrix.DELTA_INDEX[value];
      } else {
        x = ColorMatrix.DELTA_INDEX[(value<<0)]*(1-x)+ColorMatrix.DELTA_INDEX[(value<<0)+1]*x; // use linear interpolation for more granularity.
      }
      x = x*127+127;
    }
    this._multiplyMatrix([
      x/127,0,0,0,0.5*(127-x),
      0,x/127,0,0,0.5*(127-x),
      0,0,x/127,0,0.5*(127-x),
      0,0,0,1,0,
      0,0,0,0,1
    ]);
    return this;
  };

  /**
   * Adjusts the color saturation of the pixel.
   * Positive values will increase saturation, negative values will decrease saturation (trend towards greyscale).
   * @method adjustSaturation
   * @param {Number} value A value between -100 & 100.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.adjustSaturation = function(value) {
    if (value == 0 || isNaN(value)) { return this; }
    value = this._cleanValue(value,100);
    var x = 1+((value > 0) ? 3*value/100 : value/100);
    var lumR = 0.3086;
    var lumG = 0.6094;
    var lumB = 0.0820;
    this._multiplyMatrix([
      lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0,
      lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0,
      lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0,
      0,0,0,1,0,
      0,0,0,0,1
    ]);
    return this;
  };


  /**
   * Adjusts the hue of the pixel color.
   * @method adjustHue
   * @param {Number} value A value between -180 & 180.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.adjustHue = function(value) {
    if (value == 0 || isNaN(value)) { return this; }
    value = this._cleanValue(value,180)/180*Math.PI;
    var cosVal = Math.cos(value);
    var sinVal = Math.sin(value);
    var lumR = 0.213;
    var lumG = 0.715;
    var lumB = 0.072;
    this._multiplyMatrix([
      lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0,
      lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0,
      lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0,
      0,0,0,1,0,
      0,0,0,0,1
    ]);
    return this;
  };

  /**
   * Concatenates (multiplies) the specified matrix with this one.
   * @method concat
   * @param {Array} matrix An array or ColorMatrix instance.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.concat = function(matrix) {
    matrix = this._fixMatrix(matrix);
    if (matrix.length != ColorMatrix.LENGTH) { return this; }
    this._multiplyMatrix(matrix);
    return this;
  };

  /**
   * Returns a clone of this ColorMatrix.
   * @method clone
   * @return {ColorMatrix} A clone of this ColorMatrix.
   **/
  p.clone = function() {
    return (new ColorMatrix()).copy(this);
  };

  /**
   * Return a length 25 (5x5) array instance containing this matrix's values.
   * @method toArray
   * @return {Array} An array holding this matrix's values.
   **/
  p.toArray = function() {
    var arr = [];
    for (var i= 0, l=ColorMatrix.LENGTH; i<l; i++) {
      arr[i] = this[i];
    }
    return arr;
  };

  /**
   * Copy the specified matrix's values to this matrix.
   * @method copy
   * @param {Array} matrix An array or ColorMatrix instance.
   * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
   * @chainable
   **/
  p.copy = function(matrix) {
    var l = ColorMatrix.LENGTH;
    for (var i=0;i<l;i++) {
      this[i] = matrix[i];
    }
    return this;
  };
  
  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
    return "[ColorMatrix]";
  };


// private methods:
  /**
   * @method _multiplyMatrix
   * @param {Array} matrix
   * @protected
   **/
  p._multiplyMatrix = function(matrix) {
    var i, j, k, col = [];

    for (i=0;i<5;i++) {
      for (j=0;j<5;j++) {
        col[j] = this[j+i*5];
      }
      for (j=0;j<5;j++) {
        var val=0;
        for (k=0;k<5;k++) {
          val += matrix[j+k*5]*col[k];
        }
        this[j+i*5] = val;
      }
    }
  };

  /**
   * Make sure values are within the specified range, hue has a limit of 180, brightness is 255, others are 100.
   * @method _cleanValue
   * @param {Number} value The raw number
   * @param {Number} limit The maximum that the number can be. The minimum is the limit * -1.
   * @protected
   **/
  p._cleanValue = function(value, limit) {
    return Math.min(limit,Math.max(-limit,value));
  };

  /**
   * Makes sure matrixes are 5x5 (25 long).
   * @method _fixMatrix
   * @param {Array} matrix
   * @protected
   **/
  p._fixMatrix = function(matrix) {
    if (matrix instanceof ColorMatrix) { matrix = matrix.toArray(); }
    if (matrix.length < ColorMatrix.LENGTH) {
      matrix = matrix.slice(0,matrix.length).concat(ColorMatrix.IDENTITY_MATRIX.slice(matrix.length,ColorMatrix.LENGTH));
    } else if (matrix.length > ColorMatrix.LENGTH) {
      matrix = matrix.slice(0,ColorMatrix.LENGTH);
    }
    return matrix;
  };


  createjs.ColorMatrix = ColorMatrix;
}());

//##############################################################################
// ColorMatrixFilter.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
   * Allows you to carry out complex color operations such as modifying saturation, brightness, or inverting. See the
   * {{#crossLink "ColorMatrix"}}{{/crossLink}} for more information on changing colors. For an easier color transform,
   * consider the {{#crossLink "ColorFilter"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   * This example creates a red circle, inverts its hue, and then saturates it to brighten it up.
   *
   *      var shape = new createjs.Shape().set({x:100,y:100});
   *      shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
   *
   *      var matrix = new createjs.ColorMatrix().adjustHue(180).adjustSaturation(100);
   *      shape.filters = [
   *          new createjs.ColorMatrixFilter(matrix)
   *      ];
   *
   *      shape.cache(-50, -50, 100, 100);
   *
   * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
   * @class ColorMatrixFilter
   * @constructor
   * @extends Filter
   * @param {Array | ColorMatrix} matrix A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}}
   * class.
   **/
  function ColorMatrixFilter(matrix) {
  
    
  // public properties:
    /**
     * A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}}
     * @property matrix
     * @type Array | ColorMatrix
     **/
    this.matrix = matrix;
  }
  var p = createjs.extend(ColorMatrixFilter, createjs.Filter);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
  

// public methods:
  /** docced in super class **/
  p.toString = function() {
    return "[ColorMatrixFilter]";
  };

  /** docced in super class **/
  p.clone = function() {
    return new ColorMatrixFilter(this.matrix);
  };

// private methods:
  /** docced in super class **/
  p._applyFilter = function(imageData) { 
    var data = imageData.data;
    var l = data.length;
    var r,g,b,a;
    var mtx = this.matrix;
    var m0 =  mtx[0],  m1 =  mtx[1],  m2 =  mtx[2],  m3 =  mtx[3],  m4 =  mtx[4];
    var m5 =  mtx[5],  m6 =  mtx[6],  m7 =  mtx[7],  m8 =  mtx[8],  m9 =  mtx[9];
    var m10 = mtx[10], m11 = mtx[11], m12 = mtx[12], m13 = mtx[13], m14 = mtx[14];
    var m15 = mtx[15], m16 = mtx[16], m17 = mtx[17], m18 = mtx[18], m19 = mtx[19];

    for (var i=0; i<l; i+=4) {
      r = data[i];
      g = data[i+1];
      b = data[i+2];
      a = data[i+3];
      data[i] = r*m0+g*m1+b*m2+a*m3+m4; // red
      data[i+1] = r*m5+g*m6+b*m7+a*m8+m9; // green
      data[i+2] = r*m10+g*m11+b*m12+a*m13+m14; // blue
      data[i+3] = r*m15+g*m16+b*m17+a*m18+m19; // alpha
    }
    return true;
  };


  createjs.ColorMatrixFilter = createjs.promote(ColorMatrixFilter, "Filter");
}());

//##############################################################################
// Touch.js
//##############################################################################

(function() {
  "use strict";


// constructor:
  /**
 * Global utility for working with multi-touch enabled devices in EaselJS. Currently supports W3C Touch API (iOS and
 * modern Android browser) and the Pointer API (IE), including ms-prefixed events in IE10, and unprefixed in IE11.
 *
 * Ensure that you {{#crossLink "Touch/disable"}}{{/crossLink}} touch when cleaning up your application. You do not have
 * to check if touch is supported to enable it, as it will fail gracefully if it is not supported.
 *
 * <h4>Example</h4>
 *
 *      var stage = new createjs.Stage("canvasId");
 *      createjs.Touch.enable(stage);
 *
 * <strong>Note:</strong> It is important to disable Touch on a stage that you are no longer using:
 *
 *      createjs.Touch.disable(stage);
 *
 * @class Touch
 * @static
 **/
  function Touch() {
    throw "Touch cannot be instantiated";
  }


// public static methods:
  /**
   * Returns `true` if touch is supported in the current browser.
   * @method isSupported
   * @return {Boolean} Indicates whether touch is supported in the current browser.
   * @static
   **/
  Touch.isSupported = function() {
    return  !!(('ontouchstart' in window) // iOS & Android
      || (window.navigator['msPointerEnabled'] && window.navigator['msMaxTouchPoints'] > 0) // IE10
      || (window.navigator['pointerEnabled'] && window.navigator['maxTouchPoints'] > 0)); // IE11+
  };

  /**
   * Enables touch interaction for the specified EaselJS {{#crossLink "Stage"}}{{/crossLink}}. Currently supports iOS
   * (and compatible browsers, such as modern Android browsers), and IE10/11. Supports both single touch and
   * multi-touch modes. Extends the EaselJS {{#crossLink "MouseEvent"}}{{/crossLink}} model, but without support for
   * double click or over/out events. See the MouseEvent {{#crossLink "MouseEvent/pointerId:property"}}{{/crossLink}}
   * for more information.
   * @method enable
   * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to enable touch on.
   * @param {Boolean} [singleTouch=false] If `true`, only a single touch will be active at a time.
   * @param {Boolean} [allowDefault=false] If `true`, then default gesture actions (ex. scrolling, zooming) will be
   * allowed when the user is interacting with the target canvas.
   * @return {Boolean} Returns `true` if touch was successfully enabled on the target stage.
   * @static
   **/
  Touch.enable = function(stage, singleTouch, allowDefault) {
    if (!stage || !stage.canvas || !Touch.isSupported()) { return false; }
    if (stage.__touch) { return true; }

    // inject required properties on stage:
    stage.__touch = {pointers:{}, multitouch:!singleTouch, preventDefault:!allowDefault, count:0};

    // note that in the future we may need to disable the standard mouse event model before adding
    // these to prevent duplicate calls. It doesn't seem to be an issue with iOS devices though.
    if ('ontouchstart' in window) { Touch._IOS_enable(stage); }
    else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_enable(stage); }
    return true;
  };

  /**
   * Removes all listeners that were set up when calling `Touch.enable()` on a stage.
   * @method disable
   * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to disable touch on.
   * @static
   **/
  Touch.disable = function(stage) {
    if (!stage) { return; }
    if ('ontouchstart' in window) { Touch._IOS_disable(stage); }
    else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_disable(stage); }
    
    delete stage.__touch;
  };


// Private static methods:
  /**
   * @method _IOS_enable
   * @protected
   * @param {Stage} stage
   * @static
   **/
  Touch._IOS_enable = function(stage) {
    var canvas = stage.canvas;
    var f = stage.__touch.f = function(e) { Touch._IOS_handleEvent(stage,e); };
    canvas.addEventListener("touchstart", f, false);
    canvas.addEventListener("touchmove", f, false);
    canvas.addEventListener("touchend", f, false);
    canvas.addEventListener("touchcancel", f, false);
  };

  /**
   * @method _IOS_disable
   * @protected
   * @param {Stage} stage
   * @static
   **/
  Touch._IOS_disable = function(stage) {
    var canvas = stage.canvas;
    if (!canvas) { return; }
    var f = stage.__touch.f;
    canvas.removeEventListener("touchstart", f, false);
    canvas.removeEventListener("touchmove", f, false);
    canvas.removeEventListener("touchend", f, false);
    canvas.removeEventListener("touchcancel", f, false);
  };

  /**
   * @method _IOS_handleEvent
   * @param {Stage} stage
   * @param {Object} e The event to handle
   * @protected
   * @static
   **/
  Touch._IOS_handleEvent = function(stage, e) {
    if (!stage) { return; }
    if (stage.__touch.preventDefault) { e.preventDefault&&e.preventDefault(); }
    var touches = e.changedTouches;
    var type = e.type;
    for (var i= 0,l=touches.length; i<l; i++) {
      var touch = touches[i];
      var id = touch.identifier;
      if (touch.target != stage.canvas) { continue; }

      if (type == "touchstart") {
        this._handleStart(stage, id, e, touch.pageX, touch.pageY);
      } else if (type == "touchmove") {
        this._handleMove(stage, id, e, touch.pageX, touch.pageY);
      } else if (type == "touchend" || type == "touchcancel") {
        this._handleEnd(stage, id, e);
      }
    }
  };

  /**
   * @method _IE_enable
   * @protected
   * @param {Stage} stage
   * @static
   **/
  Touch._IE_enable = function(stage) {
    var canvas = stage.canvas;
    var f = stage.__touch.f = function(e) { Touch._IE_handleEvent(stage,e); };

    if (window.navigator["pointerEnabled"] === undefined) {
      canvas.addEventListener("MSPointerDown", f, false);
      window.addEventListener("MSPointerMove", f, false);
      window.addEventListener("MSPointerUp", f, false);
      window.addEventListener("MSPointerCancel", f, false);
      if (stage.__touch.preventDefault) { canvas.style.msTouchAction = "none"; }
    } else {
      canvas.addEventListener("pointerdown", f, false);
      window.addEventListener("pointermove", f, false);
      window.addEventListener("pointerup", f, false);
      window.addEventListener("pointercancel", f, false);
      if (stage.__touch.preventDefault) { canvas.style.touchAction = "none"; }

    }
    stage.__touch.activeIDs = {};
  };

  /**
   * @method _IE_disable
   * @protected
   * @param {Stage} stage
   * @static
   **/
  Touch._IE_disable = function(stage) {
    var f = stage.__touch.f;

    if (window.navigator["pointerEnabled"] === undefined) {
      window.removeEventListener("MSPointerMove", f, false);
      window.removeEventListener("MSPointerUp", f, false);
      window.removeEventListener("MSPointerCancel", f, false);
      if (stage.canvas) {
        stage.canvas.removeEventListener("MSPointerDown", f, false);
      }
    } else {
      window.removeEventListener("pointermove", f, false);
      window.removeEventListener("pointerup", f, false);
      window.removeEventListener("pointercancel", f, false);
      if (stage.canvas) {
        stage.canvas.removeEventListener("pointerdown", f, false);
      }
    }
  };

  /**
   * @method _IE_handleEvent
   * @param {Stage} stage
   * @param {Object} e The event to handle.
   * @protected
   * @static
   **/
  Touch._IE_handleEvent = function(stage, e) {
    if (!stage) { return; }
    if (stage.__touch.preventDefault) { e.preventDefault && e.preventDefault(); }
    var type = e.type;
    var id = e.pointerId;
    var ids = stage.__touch.activeIDs;

    if (type == "MSPointerDown" || type == "pointerdown") {
      if (e.srcElement != stage.canvas) { return; }
      ids[id] = true;
      this._handleStart(stage, id, e, e.pageX, e.pageY);
    } else if (ids[id]) { // it's an id we're watching
      if (type == "MSPointerMove" || type == "pointermove") {
        this._handleMove(stage, id, e, e.pageX, e.pageY);
      } else if (type == "MSPointerUp" || type == "MSPointerCancel"
          || type == "pointerup" || type == "pointercancel") {
        delete(ids[id]);
        this._handleEnd(stage, id, e);
      }
    }
  };

  /**
   * @method _handleStart
   * @param {Stage} stage
   * @param {String|Number} id
   * @param {Object} e
   * @param {Number} x
   * @param {Number} y
   * @protected
   **/
  Touch._handleStart = function(stage, id, e, x, y) {
    var props = stage.__touch;
    if (!props.multitouch && props.count) { return; }
    var ids = props.pointers;
    if (ids[id]) { return; }
    ids[id] = true;
    props.count++;
    stage._handlePointerDown(id, e, x, y);
  };

  /**
   * @method _handleMove
   * @param {Stage} stage
   * @param {String|Number} id
   * @param {Object} e
   * @param {Number} x
   * @param {Number} y
   * @protected
   **/
  Touch._handleMove = function(stage, id, e, x, y) {
    if (!stage.__touch.pointers[id]) { return; }
    stage._handlePointerMove(id, e, x, y);
  };

  /**
   * @method _handleEnd
   * @param {Stage} stage
   * @param {String|Number} id
   * @param {Object} e
   * @protected
   **/
  Touch._handleEnd = function(stage, id, e) {
    // TODO: cancel should be handled differently for proper UI (ex. an up would trigger a click, a cancel would more closely resemble an out).
    var props = stage.__touch;
    var ids = props.pointers;
    if (!ids[id]) { return; }
    props.count--;
    stage._handlePointerUp(id, e, true);
    delete(ids[id]);
  };


  createjs.Touch = Touch;
}());

//##############################################################################
// version.js
//##############################################################################

(function() {
  "use strict";

  /**
   * Static class holding library specific information such as the version and buildDate of
   * the library.
   * @class EaselJS
   **/
  var s = createjs.EaselJS = createjs.EaselJS || {};

  /**
   * The version string for this release.
   * @property version
   * @type String
   * @static
   **/
  s.version = /*=version*/"0.8.1"; // injected by build process

  /**
   * The build date for this release in UTC format.
   * @property buildDate
   * @type String
   * @static
   **/
  s.buildDate = /*=date*/"Thu, 21 May 2015 16:17:39 GMT"; // injected by build process

})();

//##############################################################################
// version.js
//##############################################################################

(function () {
  "use strict";

  /**
   * Static class holding library specific information such as the version and buildDate of the library.
   * @class PreloadJS
   **/
  var s = createjs.PreloadJS = createjs.PreloadJS || {};

  /**
   * The version string for this release.
   * @property version
   * @type {String}
   * @static
   **/
  s.version = /*=version*/"0.6.1"; // injected by build process

  /**
   * The build date for this release in UTC format.
   * @property buildDate
   * @type {String}
   * @static
   **/
  s.buildDate = /*=date*/"Thu, 21 May 2015 16:17:37 GMT"; // injected by build process

})();

//##############################################################################
// proxy.js
//##############################################################################

/**
 * Various utilities that the CreateJS Suite uses. Utilities are created as separate files, and will be available on the
 * createjs namespace directly.
 *
 * <h4>Example</h4>
 *
 *      myObject.addEventListener("change", createjs.proxy(myMethod, scope));
 *
 * @class Utility Methods
 * @main Utility Methods
 */

(function() {
  "use strict";

  /**
   * A function proxy for methods. By default, JavaScript methods do not maintain scope, so passing a method as a
   * callback will result in the method getting called in the scope of the caller. Using a proxy ensures that the
   * method gets called in the correct scope.
   *
   * Additional arguments can be passed that will be applied to the function when it is called.
   *
   * <h4>Example</h4>
   *
   *      myObject.addEventListener("event", createjs.proxy(myHandler, this, arg1, arg2));
   *
   *      function myHandler(arg1, arg2) {
   *           // This gets called when myObject.myCallback is executed.
   *      }
   *
   * @method proxy
   * @param {Function} method The function to call
   * @param {Object} scope The scope to call the method name on
   * @param {mixed} [arg] * Arguments that are appended to the callback for additional params.
   * @public
   * @static
   */
  createjs.proxy = function (method, scope) {
    var aArgs = Array.prototype.slice.call(arguments, 2);
    return function () {
      return method.apply(scope, Array.prototype.slice.call(arguments, 0).concat(aArgs));
    };
  }

}());

//##############################################################################
// BrowserDetect.js
//##############################################################################

/**
 * @class Utility Methods
 */
(function() {
  "use strict";

  /**
   * An object that determines the current browser, version, operating system, and other environment
   * variables via user agent string.
   *
   * Used for audio because feature detection is unable to detect the many limitations of mobile devices.
   *
   * <h4>Example</h4>
   *
   *      if (createjs.BrowserDetect.isIOS) { // do stuff }
   *
   * @property BrowserDetect
   * @type {Object}
   * @param {Boolean} isFirefox True if our browser is Firefox.
   * @param {Boolean} isOpera True if our browser is opera.
   * @param {Boolean} isChrome True if our browser is Chrome.  Note that Chrome for Android returns true, but is a
   * completely different browser with different abilities.
   * @param {Boolean} isIOS True if our browser is safari for iOS devices (iPad, iPhone, and iPod).
   * @param {Boolean} isAndroid True if our browser is Android.
   * @param {Boolean} isBlackberry True if our browser is Blackberry.
   * @constructor
   * @static
   */
  function BrowserDetect() {
    throw "BrowserDetect cannot be instantiated";
  }

  var agent = BrowserDetect.agent = window.navigator.userAgent;
  BrowserDetect.isWindowPhone = (agent.indexOf("IEMobile") > -1) || (agent.indexOf("Windows Phone") > -1);
  BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1);
  BrowserDetect.isOpera = (window.opera != null);
  BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1);  // NOTE that Chrome on Android returns true but is a completely different browser with different abilities
  BrowserDetect.isIOS = (agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1) && !BrowserDetect.isWindowPhone;
  BrowserDetect.isAndroid = (agent.indexOf("Android") > -1) && !BrowserDetect.isWindowPhone;
  BrowserDetect.isBlackberry = (agent.indexOf("Blackberry") > -1);

  createjs.BrowserDetect = BrowserDetect;

}());

//##############################################################################
// ErrorEvent.js
//##############################################################################

(function() {
  "use strict";

  /**
   * A general error {{#crossLink "Event"}}{{/crossLink}}, that describes an error that occurred, as well as any details.
   * @class ErrorEvent
   * @param {String} [title] The error title
   * @param {String} [message] The error description
   * @param {Object} [data] Additional error data
   * @constructor
   */
  function ErrorEvent(title, message, data) {
    this.Event_constructor("error");

    /**
     * The short error title, which indicates the type of error that occurred.
     * @property title
     * @type String
     */
    this.title = title;

    /**
     * The verbose error message, containing details about the error.
     * @property message
     * @type String
     */
    this.message = message;

    /**
     * Additional data attached to an error.
     * @property data
     * @type {Object}
     */
    this.data = data;
  }

  var p = createjs.extend(ErrorEvent, createjs.Event);

  p.clone = function() {
    return new createjs.ErrorEvent(this.title, this.message, this.data);
  };

  createjs.ErrorEvent = createjs.promote(ErrorEvent, "Event");

}());

//##############################################################################
// ProgressEvent.js
//##############################################################################

(function (scope) {
  "use strict";

  // constructor
  /**
   * A CreateJS {{#crossLink "Event"}}{{/crossLink}} that is dispatched when progress changes.
   * @class ProgressEvent
   * @param {Number} loaded The amount that has been loaded. This can be any number relative to the total.
   * @param {Number} [total=1] The total amount that will load. This will default to 1, so if the `loaded` value is
   * a percentage (between 0 and 1), it can be omitted.
   * @todo Consider having this event be a "fileprogress" event as well
   * @constructor
   */
  function ProgressEvent(loaded, total) {
    this.Event_constructor("progress");

    /**
     * The amount that has been loaded (out of a total amount)
     * @property loaded
     * @type {Number}
     */
    this.loaded = loaded;

    /**
     * The total "size" of the load.
     * @property total
     * @type {Number}
     * @default 1
     */
    this.total = (total == null) ? 1 : total;

    /**
     * The percentage (out of 1) that the load has been completed. This is calculated using `loaded/total`.
     * @property progress
     * @type {Number}
     * @default 0
     */
    this.progress = (total == 0) ? 0 : this.loaded / this.total;
  };

  var p = createjs.extend(ProgressEvent, createjs.Event);

  /**
   * Returns a clone of the ProgressEvent instance.
   * @method clone
   * @return {ProgressEvent} a clone of the Event instance.
   **/
  p.clone = function() {
    return new createjs.ProgressEvent(this.loaded, this.total);
  };

  createjs.ProgressEvent = createjs.promote(ProgressEvent, "Event");

}(window));

//##############################################################################
// json3.js
//##############################################################################

/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
;(function () {
  // Detect the `define` function exposed by asynchronous module loaders. The
  // strict `define` check is necessary for compatibility with `r.js`.
  var isLoader = typeof define === "function" && define.amd;

  // A set of types used to distinguish objects from primitives.
  var objectTypes = {
    "function": true,
    "object": true
  };

  // Detect the `exports` object exposed by CommonJS implementations.
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;

  // Use the `global` object exposed by Node (including Browserify via
  // `insert-module-globals`), Narwhal, and Ringo as the default context,
  // and the `window` object in browsers. Rhino exports a `global` function
  // instead.
  var root = objectTypes[typeof window] && window || this,
      freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global;

  if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) {
    root = freeGlobal;
  }

  // Public: Initializes JSON 3 using the given `context` object, attaching the
  // `stringify` and `parse` functions to the specified `exports` object.
  function runInContext(context, exports) {
    context || (context = root["Object"]());
    exports || (exports = root["Object"]());

    // Native constructor aliases.
    var Number = context["Number"] || root["Number"],
        String = context["String"] || root["String"],
        Object = context["Object"] || root["Object"],
        Date = context["Date"] || root["Date"],
        SyntaxError = context["SyntaxError"] || root["SyntaxError"],
        TypeError = context["TypeError"] || root["TypeError"],
        Math = context["Math"] || root["Math"],
        nativeJSON = context["JSON"] || root["JSON"];

    // Delegate to the native `stringify` and `parse` implementations.
    if (typeof nativeJSON == "object" && nativeJSON) {
      exports.stringify = nativeJSON.stringify;
      exports.parse = nativeJSON.parse;
    }

    // Convenience aliases.
    var objectProto = Object.prototype,
        getClass = objectProto.toString,
        isProperty, forEach, undef;

    // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
    var isExtended = new Date(-3509827334573292);
    try {
      // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
      // results for certain dates in Opera >= 10.53.
      isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
        // Safari < 2.0.2 stores the internal millisecond time value correctly,
        // but clips the values returned by the date methods to the range of
        // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
        isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
    } catch (exception) {}

    // Internal: Determines whether the native `JSON.stringify` and `parse`
    // implementations are spec-compliant. Based on work by Ken Snyder.
    function has(name) {
      if (has[name] !== undef) {
        // Return cached feature test result.
        return has[name];
      }
      var isSupported;
      if (name == "bug-string-char-index") {
        // IE <= 7 doesn't support accessing string characters using square
        // bracket notation. IE 8 only supports this for primitives.
        isSupported = "a"[0] != "a";
      } else if (name == "json") {
        // Indicates whether both `JSON.stringify` and `JSON.parse` are
        // supported.
        isSupported = has("json-stringify") && has("json-parse");
      } else {
        var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
        // Test `JSON.stringify`.
        if (name == "json-stringify") {
          var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended;
          if (stringifySupported) {
            // A test function object with a custom `toJSON` method.
            (value = function () {
              return 1;
            }).toJSON = value;
            try {
              stringifySupported =
                // Firefox 3.1b1 and b2 serialize string, number, and boolean
                // primitives as object literals.
                stringify(0) === "0" &&
                // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
                // literals.
                stringify(new Number()) === "0" &&
                stringify(new String()) == '""' &&
                // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
                // does not define a canonical JSON representation (this applies to
                // objects with `toJSON` properties as well, *unless* they are nested
                // within an object or array).
                stringify(getClass) === undef &&
                // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
                // FF 3.1b3 pass this test.
                stringify(undef) === undef &&
                // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
                // respectively, if the value is omitted entirely.
                stringify() === undef &&
                // FF 3.1b1, 2 throw an error if the given value is not a number,
                // string, array, object, Boolean, or `null` literal. This applies to
                // objects with custom `toJSON` methods as well, unless they are nested
                // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
                // methods entirely.
                stringify(value) === "1" &&
                stringify([value]) == "[1]" &&
                // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
                // `"[null]"`.
                stringify([undef]) == "[null]" &&
                // YUI 3.0.0b1 fails to serialize `null` literals.
                stringify(null) == "null" &&
                // FF 3.1b1, 2 halts serialization if an array contains a function:
                // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
                // elides non-JSON values from objects and arrays, unless they
                // define custom `toJSON` methods.
                stringify([undef, getClass, null]) == "[null,null,null]" &&
                // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
                // where character escape codes are expected (e.g., `\b` => `\u0008`).
                stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
                // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
                stringify(null, value) === "1" &&
                stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
                // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
                // serialize extended years.
                stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
                // The milliseconds are optional in ES 5, but required in 5.1.
                stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
                // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
                // four-digit years instead of six-digit years. Credits: @Yaffle.
                stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
                // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
                // values less than 1000. Credits: @Yaffle.
                stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
            } catch (exception) {
              stringifySupported = false;
            }
          }
          isSupported = stringifySupported;
        }
        // Test `JSON.parse`.
        if (name == "json-parse") {
          var parse = exports.parse;
          if (typeof parse == "function") {
            try {
              // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
              // Conforming implementations should also coerce the initial argument to
              // a string prior to parsing.
              if (parse("0") === 0 && !parse(false)) {
                // Simple parsing test.
                value = parse(serialized);
                var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
                if (parseSupported) {
                  try {
                    // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
                    parseSupported = !parse('"\t"');
                  } catch (exception) {}
                  if (parseSupported) {
                    try {
                      // FF 4.0 and 4.0.1 allow leading `+` signs and leading
                      // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
                      // certain octal literals.
                      parseSupported = parse("01") !== 1;
                    } catch (exception) {}
                  }
                  if (parseSupported) {
                    try {
                      // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
                      // points. These environments, along with FF 3.1b1 and 2,
                      // also allow trailing commas in JSON objects and arrays.
                      parseSupported = parse("1.") !== 1;
                    } catch (exception) {}
                  }
                }
              }
            } catch (exception) {
              parseSupported = false;
            }
          }
          isSupported = parseSupported;
        }
      }
      return has[name] = !!isSupported;
    }

    if (!has("json")) {
      // Common `[[Class]]` name aliases.
      var functionClass = "[object Function]",
          dateClass = "[object Date]",
          numberClass = "[object Number]",
          stringClass = "[object String]",
          arrayClass = "[object Array]",
          booleanClass = "[object Boolean]";

      // Detect incomplete support for accessing string characters by index.
      var charIndexBuggy = has("bug-string-char-index");

      // Define additional utility methods if the `Date` methods are buggy.
      if (!isExtended) {
        var floor = Math.floor;
        // A mapping between the months of the year and the number of days between
        // January 1st and the first of the respective month.
        var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
        // Internal: Calculates the number of days between the Unix epoch and the
        // first day of the given month.
        var getDay = function (year, month) {
          return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
        };
      }

      // Internal: Determines if a property is a direct property of the given
      // object. Delegates to the native `Object#hasOwnProperty` method.
      if (!(isProperty = objectProto.hasOwnProperty)) {
        isProperty = function (property) {
          var members = {}, constructor;
          if ((members.__proto__ = null, members.__proto__ = {
            // The *proto* property cannot be set multiple times in recent
            // versions of Firefox and SeaMonkey.
            "toString": 1
          }, members).toString != getClass) {
            // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
            // supports the mutable *proto* property.
            isProperty = function (property) {
              // Capture and break the object's prototype chain (see section 8.6.2
              // of the ES 5.1 spec). The parenthesized expression prevents an
              // unsafe transformation by the Closure Compiler.
              var original = this.__proto__, result = property in (this.__proto__ = null, this);
              // Restore the original prototype chain.
              this.__proto__ = original;
              return result;
            };
          } else {
            // Capture a reference to the top-level `Object` constructor.
            constructor = members.constructor;
            // Use the `constructor` property to simulate `Object#hasOwnProperty` in
            // other environments.
            isProperty = function (property) {
              var parent = (this.constructor || constructor).prototype;
              return property in this && !(property in parent && this[property] === parent[property]);
            };
          }
          members = null;
          return isProperty.call(this, property);
        };
      }

      // Internal: Normalizes the `for...in` iteration algorithm across
      // environments. Each enumerated key is yielded to a `callback` function.
      forEach = function (object, callback) {
        var size = 0, Properties, members, property;

        // Tests for bugs in the current environment's `for...in` algorithm. The
        // `valueOf` property inherits the non-enumerable flag from
        // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
        (Properties = function () {
          this.valueOf = 0;
        }).prototype.valueOf = 0;

        // Iterate over a new instance of the `Properties` class.
        members = new Properties();
        for (property in members) {
          // Ignore all properties inherited from `Object.prototype`.
          if (isProperty.call(members, property)) {
            size++;
          }
        }
        Properties = members = null;

        // Normalize the iteration algorithm.
        if (!size) {
          // A list of non-enumerable properties inherited from `Object.prototype`.
          members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
          // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
          // properties.
          forEach = function (object, callback) {
            var isFunction = getClass.call(object) == functionClass, property, length;
            var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty;
            for (property in object) {
              // Gecko <= 1.0 enumerates the `prototype` property of functions under
              // certain conditions; IE does not.
              if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
                callback(property);
              }
            }
            // Manually invoke the callback for each non-enumerable property.
            for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
          };
        } else if (size == 2) {
          // Safari <= 2.0.4 enumerates shadowed properties twice.
          forEach = function (object, callback) {
            // Create a set of iterated properties.
            var members = {}, isFunction = getClass.call(object) == functionClass, property;
            for (property in object) {
              // Store each property name to prevent double enumeration. The
              // `prototype` property of functions is not enumerated due to cross-
              // environment inconsistencies.
              if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
                callback(property);
              }
            }
          };
        } else {
          // No bugs detected; use the standard `for...in` algorithm.
          forEach = function (object, callback) {
            var isFunction = getClass.call(object) == functionClass, property, isConstructor;
            for (property in object) {
              if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
                callback(property);
              }
            }
            // Manually invoke the callback for the `constructor` property due to
            // cross-environment inconsistencies.
            if (isConstructor || isProperty.call(object, (property = "constructor"))) {
              callback(property);
            }
          };
        }
        return forEach(object, callback);
      };

      // Public: Serializes a JavaScript `value` as a JSON string. The optional
      // `filter` argument may specify either a function that alters how object and
      // array members are serialized, or an array of strings and numbers that
      // indicates which properties should be serialized. The optional `width`
      // argument may be either a string or number that specifies the indentation
      // level of the output.
      if (!has("json-stringify")) {
        // Internal: A map of control characters and their escaped equivalents.
        var Escapes = {
          92: "\\\\",
          34: '\\"',
          8: "\\b",
          12: "\\f",
          10: "\\n",
          13: "\\r",
          9: "\\t"
        };

        // Internal: Converts `value` into a zero-padded string such that its
        // length is at least equal to `width`. The `width` must be <= 6.
        var leadingZeroes = "000000";
        var toPaddedString = function (width, value) {
          // The `|| 0` expression is necessary to work around a bug in
          // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
          return (leadingZeroes + (value || 0)).slice(-width);
        };

        // Internal: Double-quotes a string `value`, replacing all ASCII control
        // characters (characters with code unit values between 0 and 31) with
        // their escaped equivalents. This is an implementation of the
        // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
        var unicodePrefix = "\\u00";
        var quote = function (value) {
          var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10;
          var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value);
          for (; index < length; index++) {
            var charCode = value.charCodeAt(index);
            // If the character is a control character, append its Unicode or
            // shorthand escape sequence; otherwise, append the character as-is.
            switch (charCode) {
              case 8: case 9: case 10: case 12: case 13: case 34: case 92:
                result += Escapes[charCode];
                break;
              default:
                if (charCode < 32) {
                  result += unicodePrefix + toPaddedString(2, charCode.toString(16));
                  break;
                }
                result += useCharIndex ? symbols[index] : value.charAt(index);
            }
          }
          return result + '"';
        };

        // Internal: Recursively serializes an object. Implements the
        // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
        var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
          var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
          try {
            // Necessary for host object support.
            value = object[property];
          } catch (exception) {}
          if (typeof value == "object" && value) {
            className = getClass.call(value);
            if (className == dateClass && !isProperty.call(value, "toJSON")) {
              if (value > -1 / 0 && value < 1 / 0) {
                // Dates are serialized according to the `Date#toJSON` method
                // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
                // for the ISO 8601 date time string format.
                if (getDay) {
                  // Manually compute the year, month, date, hours, minutes,
                  // seconds, and milliseconds if the `getUTC*` methods are
                  // buggy. Adapted from @Yaffle's `date-shim` project.
                  date = floor(value / 864e5);
                  for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
                  for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
                  date = 1 + date - getDay(year, month);
                  // The `time` value specifies the time within the day (see ES
                  // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
                  // to compute `A modulo B`, as the `%` operator does not
                  // correspond to the `modulo` operation for negative numbers.
                  time = (value % 864e5 + 864e5) % 864e5;
                  // The hours, minutes, seconds, and milliseconds are obtained by
                  // decomposing the time within the day. See section 15.9.1.10.
                  hours = floor(time / 36e5) % 24;
                  minutes = floor(time / 6e4) % 60;
                  seconds = floor(time / 1e3) % 60;
                  milliseconds = time % 1e3;
                } else {
                  year = value.getUTCFullYear();
                  month = value.getUTCMonth();
                  date = value.getUTCDate();
                  hours = value.getUTCHours();
                  minutes = value.getUTCMinutes();
                  seconds = value.getUTCSeconds();
                  milliseconds = value.getUTCMilliseconds();
                }
                // Serialize extended years correctly.
                value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
                  "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
                  // Months, dates, hours, minutes, and seconds should have two
                  // digits; milliseconds should have three.
                  "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
                  // Milliseconds are optional in ES 5.0, but required in 5.1.
                  "." + toPaddedString(3, milliseconds) + "Z";
              } else {
                value = null;
              }
            } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
              // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
              // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
              // ignores all `toJSON` methods on these objects unless they are
              // defined directly on an instance.
              value = value.toJSON(property);
            }
          }
          if (callback) {
            // If a replacement function was provided, call it to obtain the value
            // for serialization.
            value = callback.call(object, property, value);
          }
          if (value === null) {
            return "null";
          }
          className = getClass.call(value);
          if (className == booleanClass) {
            // Booleans are represented literally.
            return "" + value;
          } else if (className == numberClass) {
            // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
            // `"null"`.
            return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
          } else if (className == stringClass) {
            // Strings are double-quoted and escaped.
            return quote("" + value);
          }
          // Recursively serialize objects and arrays.
          if (typeof value == "object") {
            // Check for cyclic structures. This is a linear search; performance
            // is inversely proportional to the number of unique nested objects.
            for (length = stack.length; length--;) {
              if (stack[length] === value) {
                // Cyclic structures cannot be serialized by `JSON.stringify`.
                throw TypeError();
              }
            }
            // Add the object to the stack of traversed objects.
            stack.push(value);
            results = [];
            // Save the current indentation level and indent one additional level.
            prefix = indentation;
            indentation += whitespace;
            if (className == arrayClass) {
              // Recursively serialize array elements.
              for (index = 0, length = value.length; index < length; index++) {
                element = serialize(index, value, callback, properties, whitespace, indentation, stack);
                results.push(element === undef ? "null" : element);
              }
              result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
            } else {
              // Recursively serialize object members. Members are selected from
              // either a user-specified list of property names, or the object
              // itself.
              forEach(properties || value, function (property) {
                var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
                if (element !== undef) {
                  // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
                  // is not the empty string, let `member` {quote(property) + ":"}
                  // be the concatenation of `member` and the `space` character."
                  // The "`space` character" refers to the literal space
                  // character, not the `space` {width} argument provided to
                  // `JSON.stringify`.
                  results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
                }
              });
              result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
            }
            // Remove the object from the traversed object stack.
            stack.pop();
            return result;
          }
        };

        // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
        exports.stringify = function (source, filter, width) {
          var whitespace, callback, properties, className;
          if (objectTypes[typeof filter] && filter) {
            if ((className = getClass.call(filter)) == functionClass) {
              callback = filter;
            } else if (className == arrayClass) {
              // Convert the property names array into a makeshift set.
              properties = {};
              for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
            }
          }
          if (width) {
            if ((className = getClass.call(width)) == numberClass) {
              // Convert the `width` to an integer and create a string containing
              // `width` number of space characters.
              if ((width -= width % 1) > 0) {
                for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
              }
            } else if (className == stringClass) {
              whitespace = width.length <= 10 ? width : width.slice(0, 10);
            }
          }
          // Opera <= 7.54u2 discards the values associated with empty string keys
          // (`""`) only if they are used directly within an object member list
          // (e.g., `!("" in { "": 1})`).
          return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
        };
      }

      // Public: Parses a JSON source string.
      if (!has("json-parse")) {
        var fromCharCode = String.fromCharCode;

        // Internal: A map of escaped control characters and their unescaped
        // equivalents.
        var Unescapes = {
          92: "\\",
          34: '"',
          47: "/",
          98: "\b",
          116: "\t",
          110: "\n",
          102: "\f",
          114: "\r"
        };

        // Internal: Stores the parser state.
        var Index, Source;

        // Internal: Resets the parser state and throws a `SyntaxError`.
        var abort = function () {
          Index = Source = null;
          throw SyntaxError();
        };

        // Internal: Returns the next token, or `"$"` if the parser has reached
        // the end of the source string. A token may be a string, number, `null`
        // literal, or Boolean literal.
        var lex = function () {
          var source = Source, length = source.length, value, begin, position, isSigned, charCode;
          while (Index < length) {
            charCode = source.charCodeAt(Index);
            switch (charCode) {
              case 9: case 10: case 13: case 32:
                // Skip whitespace tokens, including tabs, carriage returns, line
                // feeds, and space characters.
                Index++;
                break;
              case 123: case 125: case 91: case 93: case 58: case 44:
                // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
                // the current position.
                value = charIndexBuggy ? source.charAt(Index) : source[Index];
                Index++;
                return value;
              case 34:
                // `"` delimits a JSON string; advance to the next character and
                // begin parsing the string. String tokens are prefixed with the
                // sentinel `@` character to distinguish them from punctuators and
                // end-of-string tokens.
                for (value = "@", Index++; Index < length;) {
                  charCode = source.charCodeAt(Index);
                  if (charCode < 32) {
                    // Unescaped ASCII control characters (those with a code unit
                    // less than the space character) are not permitted.
                    abort();
                  } else if (charCode == 92) {
                    // A reverse solidus (`\`) marks the beginning of an escaped
                    // control character (including `"`, `\`, and `/`) or Unicode
                    // escape sequence.
                    charCode = source.charCodeAt(++Index);
                    switch (charCode) {
                      case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
                        // Revive escaped control characters.
                        value += Unescapes[charCode];
                        Index++;
                        break;
                      case 117:
                        // `\u` marks the beginning of a Unicode escape sequence.
                        // Advance to the first character and validate the
                        // four-digit code point.
                        begin = ++Index;
                        for (position = Index + 4; Index < position; Index++) {
                          charCode = source.charCodeAt(Index);
                          // A valid sequence comprises four hexdigits (case-
                          // insensitive) that form a single hexadecimal value.
                          if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
                            // Invalid Unicode escape sequence.
                            abort();
                          }
                        }
                        // Revive the escaped character.
                        value += fromCharCode("0x" + source.slice(begin, Index));
                        break;
                      default:
                        // Invalid escape sequence.
                        abort();
                    }
                  } else {
                    if (charCode == 34) {
                      // An unescaped double-quote character marks the end of the
                      // string.
                      break;
                    }
                    charCode = source.charCodeAt(Index);
                    begin = Index;
                    // Optimize for the common case where a string is valid.
                    while (charCode >= 32 && charCode != 92 && charCode != 34) {
                      charCode = source.charCodeAt(++Index);
                    }
                    // Append the string as-is.
                    value += source.slice(begin, Index);
                  }
                }
                if (source.charCodeAt(Index) == 34) {
                  // Advance to the next character and return the revived string.
                  Index++;
                  return value;
                }
                // Unterminated string.
                abort();
              default:
                // Parse numbers and literals.
                begin = Index;
                // Advance past the negative sign, if one is specified.
                if (charCode == 45) {
                  isSigned = true;
                  charCode = source.charCodeAt(++Index);
                }
                // Parse an integer or floating-point value.
                if (charCode >= 48 && charCode <= 57) {
                  // Leading zeroes are interpreted as octal literals.
                  if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
                    // Illegal octal literal.
                    abort();
                  }
                  isSigned = false;
                  // Parse the integer component.
                  for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
                  // Floats cannot contain a leading decimal point; however, this
                  // case is already accounted for by the parser.
                  if (source.charCodeAt(Index) == 46) {
                    position = ++Index;
                    // Parse the decimal component.
                    for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
                    if (position == Index) {
                      // Illegal trailing decimal.
                      abort();
                    }
                    Index = position;
                  }
                  // Parse exponents. The `e` denoting the exponent is
                  // case-insensitive.
                  charCode = source.charCodeAt(Index);
                  if (charCode == 101 || charCode == 69) {
                    charCode = source.charCodeAt(++Index);
                    // Skip past the sign following the exponent, if one is
                    // specified.
                    if (charCode == 43 || charCode == 45) {
                      Index++;
                    }
                    // Parse the exponential component.
                    for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
                    if (position == Index) {
                      // Illegal empty exponent.
                      abort();
                    }
                    Index = position;
                  }
                  // Coerce the parsed value to a JavaScript number.
                  return +source.slice(begin, Index);
                }
                // A negative sign may only precede numbers.
                if (isSigned) {
                  abort();
                }
                // `true`, `false`, and `null` literals.
                if (source.slice(Index, Index + 4) == "true") {
                  Index += 4;
                  return true;
                } else if (source.slice(Index, Index + 5) == "false") {
                  Index += 5;
                  return false;
                } else if (source.slice(Index, Index + 4) == "null") {
                  Index += 4;
                  return null;
                }
                // Unrecognized token.
                abort();
            }
          }
          // Return the sentinel `$` character if the parser has reached the end
          // of the source string.
          return "$";
        };

        // Internal: Parses a JSON `value` token.
        var get = function (value) {
          var results, hasMembers;
          if (value == "$") {
            // Unexpected end of input.
            abort();
          }
          if (typeof value == "string") {
            if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
              // Remove the sentinel `@` character.
              return value.slice(1);
            }
            // Parse object and array literals.
            if (value == "[") {
              // Parses a JSON array, returning a new JavaScript array.
              results = [];
              for (;; hasMembers || (hasMembers = true)) {
                value = lex();
                // A closing square bracket marks the end of the array literal.
                if (value == "]") {
                  break;
                }
                // If the array literal contains elements, the current token
                // should be a comma separating the previous element from the
                // next.
                if (hasMembers) {
                  if (value == ",") {
                    value = lex();
                    if (value == "]") {
                      // Unexpected trailing `,` in array literal.
                      abort();
                    }
                  } else {
                    // A `,` must separate each array element.
                    abort();
                  }
                }
                // Elisions and leading commas are not permitted.
                if (value == ",") {
                  abort();
                }
                results.push(get(value));
              }
              return results;
            } else if (value == "{") {
              // Parses a JSON object, returning a new JavaScript object.
              results = {};
              for (;; hasMembers || (hasMembers = true)) {
                value = lex();
                // A closing curly brace marks the end of the object literal.
                if (value == "}") {
                  break;
                }
                // If the object literal contains members, the current token
                // should be a comma separator.
                if (hasMembers) {
                  if (value == ",") {
                    value = lex();
                    if (value == "}") {
                      // Unexpected trailing `,` in object literal.
                      abort();
                    }
                  } else {
                    // A `,` must separate each object member.
                    abort();
                  }
                }
                // Leading commas are not permitted, object property names must be
                // double-quoted strings, and a `:` must separate each property
                // name and value.
                if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
                  abort();
                }
                results[value.slice(1)] = get(lex());
              }
              return results;
            }
            // Unexpected token encountered.
            abort();
          }
          return value;
        };

        // Internal: Updates a traversed object member.
        var update = function (source, property, callback) {
          var element = walk(source, property, callback);
          if (element === undef) {
            delete source[property];
          } else {
            source[property] = element;
          }
        };

        // Internal: Recursively traverses a parsed JSON object, invoking the
        // `callback` function for each value. This is an implementation of the
        // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
        var walk = function (source, property, callback) {
          var value = source[property], length;
          if (typeof value == "object" && value) {
            // `forEach` can't be used to traverse an array in Opera <= 8.54
            // because its `Object#hasOwnProperty` implementation returns `false`
            // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
            if (getClass.call(value) == arrayClass) {
              for (length = value.length; length--;) {
                update(value, length, callback);
              }
            } else {
              forEach(value, function (property) {
                update(value, property, callback);
              });
            }
          }
          return callback.call(source, property, value);
        };

        // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
        exports.parse = function (source, callback) {
          var result, value;
          Index = 0;
          Source = "" + source;
          result = get(lex());
          // If a JSON string contains multiple tokens, it is invalid.
          if (lex() != "$") {
            abort();
          }
          // Reset the parser state.
          Index = Source = null;
          return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
        };
      }
    }

    exports["runInContext"] = runInContext;
    return exports;
  }

  if (freeExports && !isLoader) {
    // Export for CommonJS environments.
    runInContext(root, freeExports);
  } else {
    // Export for web browsers and JavaScript engines.
    var nativeJSON = root.JSON,
        previousJSON = root["JSON3"],
        isRestored = false;

    var JSON3 = runInContext(root, (root["JSON3"] = {
      // Public: Restores the original value of the global `JSON` object and
      // returns a reference to the `JSON3` object.
      "noConflict": function () {
        if (!isRestored) {
          isRestored = true;
          root.JSON = nativeJSON;
          root["JSON3"] = previousJSON;
          nativeJSON = previousJSON = null;
        }
        return JSON3;
      }
    }));

    root.JSON = {
      "parse": JSON3.parse,
      "stringify": JSON3.stringify
    };
  }

  // Export for asynchronous module loaders.
  if (isLoader) {
    define(function () {
      return JSON3;
    });
  }
}).call(this);

//##############################################################################
// DomUtils.js
//##############################################################################

(function () {

  /**
   * A few utilities for interacting with the dom.
   * @class DomUtils
   */
  var s = {};

  s.appendToHead = function (el) {
    s.getHead().appendChild(el)
  }

  s.getHead = function () {
    return document.head || document.getElementsByTagName("head")[0];
  }

  s.getBody = function () {
    return document.body || document.getElementsByTagName("body")[0];
  }

  createjs.DomUtils = s;

}());

//##############################################################################
// DataUtils.js
//##############################################################################

(function () {

  /**
   * A few data utilities for formatting different data types.
   * @class DataUtils
   */
  var s = {};

  // static methods
  /**
   * Parse XML using the DOM. This is required when preloading XML or SVG.
   * @method parseXML
   * @param {String} text The raw text or XML that is loaded by XHR.
   * @param {String} type The mime type of the XML. Use "text/xml" for XML, and  "image/svg+xml" for SVG parsing.
   * @return {XML} An XML document
   * @static
   */
  s.parseXML = function (text, type) {
    var xml = null;
    // CocoonJS does not support XML parsing with either method.

    // Most browsers will use DOMParser
    // IE fails on certain SVG files, so we have a fallback below.
    try {
      if (window.DOMParser) {
        var parser = new DOMParser();
        xml = parser.parseFromString(text, type);
      }
    } catch (e) {
    }

    // Fallback for IE support.
    if (!xml) {
      try {
        xml = new ActiveXObject("Microsoft.XMLDOM");
        xml.async = false;
        xml.loadXML(text);
      } catch (e) {
        xml = null;
      }
    }

    return xml;
  };

  /**
   * Parse a string into an Object.
   * @method parseJSON
   * @param {String} value The loaded JSON string
   * @returns {Object} A JavaScript object.
   */
  s.parseJSON = function (value) {
    if (value == null) {
      return null;
    }

    try {
      return JSON.parse(value);
    } catch (e) {
      // TODO; Handle this with a custom error?
      throw e;
    }
  };

  createjs.DataUtils = s;

}());

//##############################################################################
// LoadItem.js
//##############################################################################

(function () {
  "use strict";

  /**
   * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead,
   * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A
   * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the
   * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}}
   * @class LoadItem
   * @constructor
   * @since 0.6.0
   */
  function LoadItem() {
    /**
     * The source of the file that is being loaded. This property is <b>required</b>. The source can either be a
     * string (recommended), or an HTML tag.
     * This can also be an object, but in that case it has to include a type and be handled by a plugin.
     * @property src
     * @type {String}
     * @default null
     */
    this.src = null;

    /**
     * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also
     * be set manually. This is helpful in cases where a file does not have an extension.
     * @property type
     * @type {String}
     * @default null
     */
    this.type = null;

    /**
     * A string identifier which can be used to reference the loaded object. If none is provided, this will be
     * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}.
     * @property id
     * @type {String}
     * @default null
     */
    this.id = null;

    /**
     * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest
     * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has
     * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this
     * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in
     * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`.
     * @property maintainOrder
     * @type {Boolean}
     * @default false
     */
    this.maintainOrder = false;

    /**
     * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded.
     * @property callback
     * @type {String}
     * @default null
     */
    this.callback = null;

    /**
     * An arbitrary data object, which is included with the loaded object.
     * @property data
     * @type {Object}
     * @default null
     */
    this.data = null;

    /**
     * The request method used for HTTP calls. Both {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} or
     * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as
     * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}.
     * @property method
     * @type {String}
     * @default get
     */
    this.method = createjs.LoadItem.GET;

    /**
     * An object hash of name/value pairs to send to the server.
     * @property values
     * @type {Object}
     * @default null
     */
    this.values = null;

    /**
     * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default
     * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the
     * default headers by including them in your headers object.
     * @property headers
     * @type {Object}
     * @default null
     */
    this.headers = null;

    /**
     * Enable credentials for XHR requests.
     * @property withCredentials
     * @type {Boolean}
     * @default false
     */
    this.withCredentials = false;

    /**
     * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text
     * based files (json, xml, text, css, js).
     * @property mimeType
     * @type {String}
     * @default null
     */
    this.mimeType = null;

    /**
     * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain.
     * @property crossOrigin
     * @type {boolean}
     * @default Anonymous
     */
    this.crossOrigin = null;

    /**
     * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
     * (level one) loading, as XHR (level 2) provides its own timeout event.
     * @property loadTimeout
     * @type {Number}
     * @default 8000 (8 seconds)
     */
    this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
  };

  var p = LoadItem.prototype = {};
  var s = LoadItem;

  /**
   * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR
   * (level one) loading, as XHR (level 2) provides its own timeout event.
   * @property LOAD_TIMEOUT_DEFAULT
   * @type {number}
   * @static
   */
  s.LOAD_TIMEOUT_DEFAULT = 8000;

  /**
   * Create a LoadItem.
   * <ul>
   *     <li>String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.</li>
   *     <li>LoadItem instances are returned as-is</li>
   *     <li>Objects are returned with any needed properties added</li>
   * </ul>
   * @method create
   * @param {LoadItem|String|Object} value The load item value
   * @returns {LoadItem|Object}
   * @static
   */
  s.create = function (value) {
    if (typeof value == "string") {
      var item = new LoadItem();
      item.src = value;
      return item;
    } else if (value instanceof s) {
      return value;
    } else if (value instanceof Object && value.src) {
      if (value.loadTimeout == null) {
        value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT;
      }
      return value;
    } else {
      throw new Error("Type not recognized.");
    }
  };

  /**
   * Provides a chainable shortcut method for setting a number of properties on the instance.
   *
   * <h4>Example</h4>
   *
   *      var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true});
   *
   * @method set
   * @param {Object} props A generic object containing properties to copy to the LoadItem instance.
   * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.)
  */
  p.set = function(props) {
    for (var n in props) { this[n] = props[n]; }
    return this;
  };

  createjs.LoadItem = s;

}());

//##############################################################################
// RequestUtils.js
//##############################################################################

(function () {

  /**
   * Utilities that assist with parsing load items, and determining file types, etc.
   * @class RequestUtils
   */
  var s = {};

  /**
   * The Regular Expression used to test file URLS for an absolute path.
   * @property ABSOLUTE_PATH
   * @type {RegExp}
   * @static
   */
  s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;

  /**
   * The Regular Expression used to test file URLS for a relative path.
   * @property RELATIVE_PATH
   * @type {RegExp}
   * @static
   */
  s.RELATIVE_PATT = (/^[./]*?\//i);

  /**
   * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
   * removed.
   * @property EXTENSION_PATT
   * @type {RegExp}
   * @static
   */
  s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;

  /**
   * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
   * <ul>
   *     <li>If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
   *     `//networkPath`)</li>
   *     <li>If the path is relative. Relative paths start with `../` or `/path` (or similar)</li>
   *     <li>The file extension. This is determined by the filename with an extension. Query strings are dropped, and
   *     the file path is expected to follow the format `name.ext`.</li>
   * </ul>
   * @method parseURI
   * @param {String} path
   * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension`
   * property, which is the lowercase extension.
   * @static
   */
  s.parseURI = function (path) {
    var info = {absolute: false, relative: false};
    if (path == null) { return info; }

    // Drop the query string
    var queryIndex = path.indexOf("?");
    if (queryIndex > -1) {
      path = path.substr(0, queryIndex);
    }

    // Absolute
    var match;
    if (s.ABSOLUTE_PATT.test(path)) {
      info.absolute = true;

      // Relative
    } else if (s.RELATIVE_PATT.test(path)) {
      info.relative = true;
    }

    // Extension
    if (match = path.match(s.EXTENSION_PATT)) {
      info.extension = match[1].toLowerCase();
    }
    return info;
  };

  /**
   * Formats an object into a query string for either a POST or GET request.
   * @method formatQueryString
   * @param {Object} data The data to convert to a query string.
   * @param {Array} [query] Existing name/value pairs to append on to this query.
   * @static
   */
  s.formatQueryString = function (data, query) {
    if (data == null) {
      throw new Error('You must specify data.');
    }
    var params = [];
    for (var n in data) {
      params.push(n + '=' + escape(data[n]));
    }
    if (query) {
      params = params.concat(query);
    }
    return params.join('&');
  };

  /**
   * A utility method that builds a file path using a source and a data object, and formats it into a new path.
   * @method buildPath
   * @param {String} src The source path to add values to.
   * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the
   * path will be preserved.
   * @returns {string} A formatted string that contains the path and the supplied parameters.
   * @static
   */
  s.buildPath = function (src, data) {
    if (data == null) {
      return src;
    }

    var query = [];
    var idx = src.indexOf('?');

    if (idx != -1) {
      var q = src.slice(idx + 1);
      query = query.concat(q.split('&'));
    }

    if (idx != -1) {
      return src.slice(0, idx) + '?' + this._formatQueryString(data, query);
    } else {
      return src + '?' + this._formatQueryString(data, query);
    }
  };

  /**
   * @method isCrossDomain
   * @param {LoadItem|Object} item A load item with a `src` property.
   * @return {Boolean} If the load item is loading from a different domain than the current location.
   * @static
   */
  s.isCrossDomain = function (item) {
    var target = document.createElement("a");
    target.href = item.src;

    var host = document.createElement("a");
    host.href = location.href;

    var crossdomain = (target.hostname != "") &&
              (target.port != host.port ||
               target.protocol != host.protocol ||
               target.hostname != host.hostname);
    return crossdomain;
  };

  /**
   * @method isLocal
   * @param {LoadItem|Object} item A load item with a `src` property
   * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as
   * well.
   * @static
   */
  s.isLocal = function (item) {
    var target = document.createElement("a");
    target.href = item.src;
    return target.hostname == "" && target.protocol == "file:";
  };

  /**
   * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked
   * specifically as "binary" are loaded as binary. Note that audio is <b>not</b> a binary type, as we can not play
   * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get
   * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on
   * {{#crossLink "AbstractLoader"}}{{/crossLink}}.
   * @method isBinary
   * @param {String} type The item type.
   * @return {Boolean} If the specified type is binary.
   * @static
   */
  s.isBinary = function (type) {
    switch (type) {
      case createjs.AbstractLoader.IMAGE:
      case createjs.AbstractLoader.BINARY:
        return true;
      default:
        return false;
    }
  };

  /**
   * Check if item is a valid HTMLImageElement
   * @method isImageTag
   * @param {Object} item
   * @returns {Boolean}
   * @static
   */
  s.isImageTag = function(item) {
    return item instanceof HTMLImageElement;
  };

  /**
   * Check if item is a valid HTMLAudioElement
   * @method isAudioTag
   * @param {Object} item
   * @returns {Boolean}
   * @static
   */
  s.isAudioTag = function(item) {
    if (window.HTMLAudioElement) {
      return item instanceof HTMLAudioElement;
    } else {
      return false;
    }
  };

  /**
   * Check if item is a valid HTMLVideoElement
   * @method isVideoTag
   * @param {Object} item
   * @returns {Boolean}
   * @static
   */
  s.isVideoTag = function(item) {
    if (window.HTMLVideoElement) {
      return item instanceof HTMLVideoElement;
    } else {
      return false;
    }
  };

  /**
   * Determine if a specific type is a text-based asset, and should be loaded as UTF-8.
   * @method isText
   * @param {String} type The item type.
   * @return {Boolean} If the specified type is text.
   * @static
   */
  s.isText = function (type) {
    switch (type) {
      case createjs.AbstractLoader.TEXT:
      case createjs.AbstractLoader.JSON:
      case createjs.AbstractLoader.MANIFEST:
      case createjs.AbstractLoader.XML:
      case createjs.AbstractLoader.CSS:
      case createjs.AbstractLoader.SVG:
      case createjs.AbstractLoader.JAVASCRIPT:
      case createjs.AbstractLoader.SPRITESHEET:
        return true;
      default:
        return false;
    }
  };

  /**
   * Determine the type of the object using common extensions. Note that the type can be passed in with the load item
   * if it is an unusual extension.
   * @method getTypeByExtension
   * @param {String} extension The file extension to use to determine the load type.
   * @return {String} The determined load type (for example, <code>AbstractLoader.IMAGE</code>). Will return `null` if
   * the type can not be determined by the extension.
   * @static
   */
  s.getTypeByExtension = function (extension) {
    if (extension == null) {
      return createjs.AbstractLoader.TEXT;
    }

    switch (extension.toLowerCase()) {
      case "jpeg":
      case "jpg":
      case "gif":
      case "png":
      case "webp":
      case "bmp":
        return createjs.AbstractLoader.IMAGE;
      case "ogg":
      case "mp3":
      case "webm":
        return createjs.AbstractLoader.SOUND;
      case "mp4":
      case "webm":
      case "ts":
        return createjs.AbstractLoader.VIDEO;
      case "json":
        return createjs.AbstractLoader.JSON;
      case "xml":
        return createjs.AbstractLoader.XML;
      case "css":
        return createjs.AbstractLoader.CSS;
      case "js":
        return createjs.AbstractLoader.JAVASCRIPT;
      case 'svg':
        return createjs.AbstractLoader.SVG;
      default:
        return createjs.AbstractLoader.TEXT;
    }
  };

  createjs.RequestUtils = s;

}());

//##############################################################################
// AbstractLoader.js
//##############################################################################

(function () {
  "use strict";

// constructor
  /**
   * The base loader, which defines all the generic methods, properties, and events. All loaders extend this class,
   * including the {{#crossLink "LoadQueue"}}{{/crossLink}}.
   * @class AbstractLoader
   * @param {LoadItem|object|string} loadItem The item to be loaded.
   * @param {Boolean} [preferXHR] Determines if the LoadItem should <em>try</em> and load using XHR, or take a
   * tag-based approach, which can be better in cross-domain situations. Not all loaders can load using one or the
   * other, so this is a suggested directive.
   * @param {String} [type] The type of loader. Loader types are defined as constants on the AbstractLoader class,
   * such as {{#crossLink "IMAGE:property"}}{{/crossLink}}, {{#crossLink "CSS:property"}}{{/crossLink}}, etc.
   * @extends EventDispatcher
   */
  function AbstractLoader(loadItem, preferXHR, type) {
    this.EventDispatcher_constructor();

    // public properties
    /**
     * If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
     * used for loading do not pile up resulting in more than one `complete` {{#crossLink "Event"}}{{/crossLink}}.
     * @property loaded
     * @type {Boolean}
     * @default false
     */
    this.loaded = false;

    /**
     * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that this property
     * is readonly, so {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "LoadQueue/close"}}{{/crossLink}}
     * instead.
     * @property canceled
     * @type {Boolean}
     * @default false
     * @readonly
     */
    this.canceled = false;

    /**
     * The current load progress (percentage) for this item. This will be a number between 0 and 1.
     *
     * <h4>Example</h4>
     *
     *     var queue = new createjs.LoadQueue();
     *     queue.loadFile("largeImage.png");
     *     queue.on("progress", function() {
     *         console.log("Progress:", queue.progress, event.progress);
     *     });
     *
     * @property progress
     * @type {Number}
     * @default 0
     */
    this.progress = 0;

    /**
     * The type of item this loader will load. See {{#crossLink "AbstractLoader"}}{{/crossLink}} for a full list of
     * supported types.
     * @property type
     * @type {String}
     */
    this.type = type;

    /**
     * A formatter function that converts the loaded raw result into the final result. For example, the JSONLoader
     * converts a string of text into a JavaScript object. Not all loaders have a resultFormatter, and this property
     * can be overridden to provide custom formatting.
     *
     * Optionally, a resultFormatter can return a callback function in cases where the formatting needs to be
     * asynchronous, such as creating a new image.
     * @property resultFormatter
     * @type {Function}
     * @default null
     */
    this.resultFormatter = null;

    // protected properties
    /**
     * The {{#crossLink "LoadItem"}}{{/crossLink}} this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}},
     * but will be available on loaders such as {{#crossLink "XMLLoader"}}{{/crossLink}} and {{#crossLink "ImageLoader"}}{{/crossLink}}.
     * @property _item
     * @type {LoadItem|Object}
     * @private
     */
    if (loadItem) {
      this._item = createjs.LoadItem.create(loadItem);
    } else {
      this._item = null;
    }

    /**
     * Whether the loader will try and load content using XHR (true) or HTML tags (false).
     * @property _preferXHR
     * @type {Boolean}
     * @private
     */
    this._preferXHR = preferXHR;

    /**
     * The loaded result after it is formatted by an optional {{#crossLink "resultFormatter"}}{{/crossLink}}. For
     * items that are not formatted, this will be the same as the {{#crossLink "_rawResult:property"}}{{/crossLink}}.
     * The result is accessed using the {{#crossLink "getResult"}}{{/crossLink}} method.
     * @property _result
     * @type {Object|String}
     * @private
     */
    this._result = null;

    /**
     * The loaded result before it is formatted. The rawResult is accessed using the {{#crossLink "getResult"}}{{/crossLink}}
     * method, and passing `true`.
     * @property _rawResult
     * @type {Object|String}
     * @private
     */
    this._rawResult = null;

    /**
     * A list of items that loaders load behind the scenes. This does not include the main item the loader is
     * responsible for loading. Examples of loaders that have sub-items include the {{#crossLink "SpriteSheetLoader"}}{{/crossLink}} and
     * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
     * @property _loadItems
     * @type {null}
     * @protected
     */
    this._loadedItems = null;

    /**
     * The attribute the items loaded using tags use for the source.
     * @type {string}
     * @default null
     * @private
     */
    this._tagSrcAttribute = null;

    /**
     * An HTML tag (or similar) that a loader may use to load HTML content, such as images, scripts, etc.
     * @property _tag
     * @type {Object}
     * @private
     */
    this._tag = null;
  };

  var p = createjs.extend(AbstractLoader, createjs.EventDispatcher);
  var s = AbstractLoader;

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


  /**
   * Defines a POST request, use for a method value when loading data.
   * @property POST
   * @type {string}
   * @default post
   * @static
   */
  s.POST = "POST";

  /**
   * Defines a GET request, use for a method value when loading data.
   * @property GET
   * @type {string}
   * @default get
   * @static
   */
  s.GET = "GET";

  /**
   * The preload type for generic binary types. Note that images are loaded as binary files when using XHR.
   * @property BINARY
   * @type {String}
   * @default binary
   * @static
   * @since 0.6.0
   */
  s.BINARY = "binary";

  /**
   * The preload type for css files. CSS files are loaded using a &lt;link&gt; when loaded with XHR, or a
   * &lt;style&gt; tag when loaded with tags.
   * @property CSS
   * @type {String}
   * @default css
   * @static
   * @since 0.6.0
   */
  s.CSS = "css";

  /**
   * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an &lt;image&gt; tag.
   * @property IMAGE
   * @type {String}
   * @default image
   * @static
   * @since 0.6.0
   */
  s.IMAGE = "image";

  /**
   * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a
   * &lt;script&gt; tag.
   *
   * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into
   * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier,
   * only tag-loaded scripts are injected.
   * @property JAVASCRIPT
   * @type {String}
   * @default javascript
   * @static
   * @since 0.6.0
   */
  s.JAVASCRIPT = "javascript";

  /**
   * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a
   * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP,
   * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON
   * must contain a matching wrapper function.
   * @property JSON
   * @type {String}
   * @default json
   * @static
   * @since 0.6.0
   */
  s.JSON = "json";

  /**
   * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a
   * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON.
   * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}}
   * property is set to.
   * @property JSONP
   * @type {String}
   * @default jsonp
   * @static
   * @since 0.6.0
   */
  s.JSONP = "jsonp";

  /**
   * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded
   * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an
   * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
   * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead,
   * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to.
   * @property MANIFEST
   * @type {String}
   * @default manifest
   * @static
   * @since 0.6.0
   */
  s.MANIFEST = "manifest";

  /**
   * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an
   * &lt;audio&gt; tag.
   * @property SOUND
   * @type {String}
   * @default sound
   * @static
   * @since 0.6.0
   */
  s.SOUND = "sound";

  /**
   * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an
   * &lt;video&gt; tag.
   * @property VIDEO
   * @type {String}
   * @default video
   * @static
   * @since 0.6.0
   */
  s.VIDEO = "video";

  /**
   * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths.
   * @property SPRITESHEET
   * @type {String}
   * @default spritesheet
   * @static
   * @since 0.6.0
   */
  s.SPRITESHEET = "spritesheet";

  /**
   * The preload type for SVG files.
   * @property SVG
   * @type {String}
   * @default svg
   * @static
   * @since 0.6.0
   */
  s.SVG = "svg";

  /**
   * The preload type for text files, which is also the default file type if the type can not be determined. Text is
   * loaded as raw text.
   * @property TEXT
   * @type {String}
   * @default text
   * @static
   * @since 0.6.0
   */
  s.TEXT = "text";

  /**
   * The preload type for xml files. XML is loaded into an XML document.
   * @property XML
   * @type {String}
   * @default xml
   * @static
   * @since 0.6.0
   */
  s.XML = "xml";

// Events
  /**
   * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to
   * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}.
   * @event progress
   * @since 0.3.0
   */

  /**
   * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts.
   * @event loadstart
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @since 0.3.1
   */

  /**
   * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded.
   * @event complete
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @since 0.3.0
   */

  /**
   * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was
   * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was
   * just a regular {{#crossLink "Event"}}{{/crossLink}}.
   * @event error
   * @since 0.3.0
   */

  /**
   * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error.
   * This enables loaders to maintain internal queues, and surface file load errors.
   * @event fileerror
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The even type ("fileerror")
   * @param {LoadItem|object} The item that encountered the error
   * @since 0.6.0
   */

  /**
   * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables
   * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s
   * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a
   * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event.
   * @event fileload
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type ("fileload")
   * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
   * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
   * object will contain that value as a `src` property.
   * @param {Object} result The HTML tag or parsed result of the loaded item.
   * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
   * to a usable object.
   * @since 0.6.0
   */

  /**
   * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load.
   * This allows updates to the loader for specific loading needs, such as binary or XHR image loading.
   * @event initialize
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type ("initialize")
   * @param {AbstractLoader} loader The loader that has been initialized.
   */


  /**
   * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was
   * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
   * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will
   * be a {{#crossLink "LoadItem"}}{{/crossLink}}.
   * @method getItem
   * @return {Object} The manifest item that this loader is responsible for loading.
   * @since 0.6.0
   */
  p.getItem = function () {
    return this._item;
  };

  /**
   * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}}
   * event is dispatched.
   * @method getResult
   * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded
   * data (if it exists).
   * @return {Object}
   * @since 0.6.0
   */
  p.getResult = function (raw) {
    return raw ? this._rawResult : this._result;
  };

  /**
   * Return the `tag` this object creates or uses for loading.
   * @method getTag
   * @return {Object} The tag instance
   * @since 0.6.0
   */
  p.getTag = function () {
    return this._tag;
  };

  /**
   * Set the `tag` this item uses for loading.
   * @method setTag
   * @param {Object} tag The tag instance
   * @since 0.6.0
   */
  p.setTag = function(tag) {
    this._tag = tag;
  };

  /**
   * Begin loading the item. This method is required when using a loader by itself.
   *
   * <h4>Example</h4>
   *
   *      var queue = new createjs.LoadQueue();
   *      queue.on("complete", handleComplete);
   *      queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
   *      queue.load();
   *
   * @method load
   */
  p.load = function () {
    this._createRequest();

    this._request.on("complete", this, this);
    this._request.on("progress", this, this);
    this._request.on("loadStart", this, this);
    this._request.on("abort", this, this);
    this._request.on("timeout", this, this);
    this._request.on("error", this, this);

    var evt = new createjs.Event("initialize");
    evt.loader = this._request;
    this.dispatchEvent(evt);

    this._request.load();
  };

  /**
   * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in
   * the background), but events will not longer be dispatched.
   * @method cancel
   */
  p.cancel = function () {
    this.canceled = true;
    this.destroy();
  };

  /**
   * Clean up the loader.
   * @method destroy
   */
  p.destroy = function() {
    if (this._request) {
      this._request.removeAllEventListeners();
      this._request.destroy();
    }

    this._request = null;

    this._item = null;
    this._rawResult = null;
    this._result = null;

    this._loadItems = null;

    this.removeAllEventListeners();
  };

  /**
   * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}}
   * to expose items it loads internally.
   * @method getLoadedItems
   * @return {Array} A list of the items loaded by the loader.
   * @since 0.6.0
   */
  p.getLoadedItems = function () {
    return this._loadedItems;
  };


  // Private methods
  /**
   * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or
   * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}.
   * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}},
   * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood.
   * @method _createRequest
   * @protected
   */
  p._createRequest = function() {
    if (!this._preferXHR) {
      this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
    } else {
      this._request = new createjs.XHRRequest(this._item);
    }
  };

  /**
   * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented
   * by loaders that require tag loading.
   * @method _createTag
   * @param {String} src The tag source
   * @return {HTMLElement} The tag that was created
   * @protected
   */
  p._createTag = function(src) { return null; };

  /**
   * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}}
   * event for details on the event payload.
   * @method _sendLoadStart
   * @protected
   */
  p._sendLoadStart = function () {
    if (this._isCanceled()) { return; }
    this.dispatchEvent("loadstart");
  };

  /**
   * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}.
   * @method _sendProgress
   * @param {Number | Object} value The progress of the loaded item, or an object containing <code>loaded</code>
   * and <code>total</code> properties.
   * @protected
   */
  p._sendProgress = function (value) {
    if (this._isCanceled()) { return; }
    var event = null;
    if (typeof(value) == "number") {
      this.progress = value;
      event = new createjs.ProgressEvent(this.progress);
    } else {
      event = value;
      this.progress = value.loaded / value.total;
      event.progress = this.progress;
      if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
    }
    this.hasEventListener("progress") && this.dispatchEvent(event);
  };

  /**
   * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event
   * @method _sendComplete
   * @protected
   */
  p._sendComplete = function () {
    if (this._isCanceled()) { return; }

    this.loaded = true;

    var event = new createjs.Event("complete");
    event.rawResult = this._rawResult;

    if (this._result != null) {
      event.result = this._result;
    }

    this.dispatchEvent(event);
  };

  /**
   * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
   * event for details on the event payload.
   * @method _sendError
   * @param {ErrorEvent} event The event object containing specific error properties.
   * @protected
   */
  p._sendError = function (event) {
    if (this._isCanceled() || !this.hasEventListener("error")) { return; }
    if (event == null) {
      event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error
    }
    this.dispatchEvent(event);
  };

  /**
   * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events
   * do not cause issues after the queue has been cleaned up.
   * @method _isCanceled
   * @return {Boolean} If the loader has been canceled.
   * @protected
   */
  p._isCanceled = function () {
    if (window.createjs == null || this.canceled) {
      return true;
    }
    return false;
  };

  /**
   * A custom result formatter function, which is called just before a request dispatches its complete event. Most
   * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The
   * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`.
   * @property resultFormatter
   * @type Function
   * @return {Object} The formatted result
   * @since 0.6.0
   */
  p.resultFormatter = null;

  /**
   * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but
   * this method can be overridden for custom behaviours.
   * @method handleEvent
   * @param {Event} event The event that the internal request dispatches.
   * @protected
   * @since 0.6.0
   */
  p.handleEvent = function (event) {
    switch (event.type) {
      case "complete":
        this._rawResult = event.target._response;
        var result = this.resultFormatter && this.resultFormatter(this);
        var _this = this;
        if (result instanceof Function) {
          result(function(result) {
            _this._result = result;
            _this._sendComplete();
          });
        } else {
          this._result =  result || this._rawResult;
          this._sendComplete();
        }
        break;
      case "progress":
        this._sendProgress(event);
        break;
      case "error":
        this._sendError(event);
        break;
      case "loadstart":
        this._sendLoadStart();
        break;
      case "abort":
      case "timeout":
        if (!this._isCanceled()) {
          this.dispatchEvent(event.type);
        }
        break;
    }
  };

  /**
   * @method buildPath
   * @protected
   * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}}
   * instead.
   */
  p.buildPath = function (src, data) {
    return createjs.RequestUtils.buildPath(src, data);
  };

  /**
   * @method toString
   * @return {String} a string representation of the instance.
   */
  p.toString = function () {
    return "[PreloadJS AbstractLoader]";
  };

  createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher");

}());

//##############################################################################
// AbstractMediaLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * The AbstractMediaLoader is a base class that handles some of the shared methods and properties of loaders that
   * handle HTML media elements, such as Video and Audio.
   * @class AbstractMediaLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @param {String} type The type of media to load. Usually "video" or "audio".
   * @extends AbstractLoader
   * @constructor
   */
  function AbstractMediaLoader(loadItem, preferXHR, type) {
    this.AbstractLoader_constructor(loadItem, preferXHR, type);

    // public properties
    this.resultFormatter = this._formatResult;

    // protected properties
    this._tagSrcAttribute = "src";
  };

  var p = createjs.extend(AbstractMediaLoader, createjs.AbstractLoader);

  // static properties
  // public methods
  p.load = function () {
    // TagRequest will handle most of this, but Sound / Video need a few custom properties, so just handle them here.
    if (!this._tag) {
      this._tag = this._createTag(this._item.src);
    }

    this._tag.preload = "auto";
    this._tag.load();

    this.AbstractLoader_load();
  };

  // protected methods
  /**
   * Creates a new tag for loading if it doesn't exist yet.
   * @method _createTag
   * @private
   */
  p._createTag = function () {};


  p._createRequest = function() {
    if (!this._preferXHR) {
      this._request = new createjs.MediaTagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute);
    } else {
      this._request = new createjs.XHRRequest(this._item);
    }
  };

  /**
   * The result formatter for media files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {HTMLVideoElement|HTMLAudioElement}
   * @private
   */
  p._formatResult = function (loader) {
    this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
    this._tag.onstalled = null;
    if (this._preferXHR) {
      loader.getTag().src = loader.getResult(true);
    }
    return loader.getTag();
  };

  createjs.AbstractMediaLoader = createjs.promote(AbstractMediaLoader, "AbstractLoader");

}());

//##############################################################################
// AbstractRequest.js
//##############################################################################

(function () {
  "use strict";

  /**
   * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}},
   * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the
   * hood to get data.
   * @class AbstractRequest
   * @param {LoadItem} item
   * @constructor
   */
  var AbstractRequest = function (item) {
    this._item = item;
  };

  var p = createjs.extend(AbstractRequest, createjs.EventDispatcher);

  // public methods
  /**
   * Begin a load.
   * @method load
   */
  p.load =  function() {};

  /**
   * Clean up a request.
   * @method destroy
   */
  p.destroy = function() {};

  /**
   * Cancel an in-progress request.
   * @method cancel
   */
  p.cancel = function() {};

  createjs.AbstractRequest = createjs.promote(AbstractRequest, "EventDispatcher");

}());

//##############################################################################
// TagRequest.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts.
   * @class TagRequest
   * @param {LoadItem} loadItem
   * @param {HTMLElement} tag
   * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
   */
  function TagRequest(loadItem, tag, srcAttribute) {
    this.AbstractRequest_constructor(loadItem);

    // protected properties
    /**
     * The HTML tag instance that is used to load.
     * @property _tag
     * @type {HTMLElement}
     * @protected
     */
    this._tag = tag;

    /**
     * The tag attribute that specifies the source, such as "src", "href", etc.
     * @property _tagSrcAttribute
     * @type {String}
     * @protected
     */
    this._tagSrcAttribute = srcAttribute;

    /**
     * A method closure used for handling the tag load event.
     * @property _loadedHandler
     * @type {Function}
     * @private
     */
    this._loadedHandler = createjs.proxy(this._handleTagComplete, this);

    /**
     * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after.
     * @property _addedToDOM
     * @type {Boolean}
     * @private
     */
    this._addedToDOM = false;

    /**
     * Determines what the tags initial style.visibility was, so we can set it correctly after a load.
     *
     * @type {null}
     * @private
     */
    this._startTagVisibility = null;
  };

  var p = createjs.extend(TagRequest, createjs.AbstractRequest);

  // public methods
  p.load = function () {
    this._tag.onload = createjs.proxy(this._handleTagComplete, this);
    this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this);
    this._tag.onerror = createjs.proxy(this._handleError, this);

    var evt = new createjs.Event("initialize");
    evt.loader = this._tag;

    this.dispatchEvent(evt);

    this._hideTag();

    this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);

    this._tag[this._tagSrcAttribute] = this._item.src;

    // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail.
    if (this._tag.parentNode == null) {
      window.document.body.appendChild(this._tag);
      this._addedToDOM = true;
    }
  };

  p.destroy = function() {
    this._clean();
    this._tag = null;

    this.AbstractRequest_destroy();
  };

  // private methods
  /**
   * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT
   * and LINK tags), but other cases may exist.
   * @method _handleReadyStateChange
   * @private
   */
  p._handleReadyStateChange = function () {
    clearTimeout(this._loadTimeout);
    // This is strictly for tags in browsers that do not support onload.
    var tag = this._tag;

    // Complete is for old IE support.
    if (tag.readyState == "loaded" || tag.readyState == "complete") {
      this._handleTagComplete();
    }
  };

  /**
   * Handle any error events from the tag.
   * @method _handleError
   * @protected
   */
  p._handleError = function() {
    this._clean();
    this.dispatchEvent("error");
  };

  /**
   * Handle the tag's onload callback.
   * @method _handleTagComplete
   * @private
   */
  p._handleTagComplete = function () {
    this._rawResult = this._tag;
    this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult;

    this._clean();
    this._showTag();

    this.dispatchEvent("complete");
  };

  /**
   * The tag request has not loaded within the time specified in loadTimeout.
   * @method _handleError
   * @param {Object} event The XHR error event.
   * @private
   */
  p._handleTimeout = function () {
    this._clean();
    this.dispatchEvent(new createjs.Event("timeout"));
  };

  /**
   * Remove event listeners, but don't destroy the request object
   * @method _clean
   * @private
   */
  p._clean = function() {
    this._tag.onload = null;
    this._tag.onreadystatechange = null;
    this._tag.onerror = null;
    if (this._addedToDOM && this._tag.parentNode != null) {
      this._tag.parentNode.removeChild(this._tag);
    }
    clearTimeout(this._loadTimeout);
  };

  p._hideTag = function() {
    this._startTagVisibility = this._tag.style.visibility;
    this._tag.style.visibility = "hidden";
  };

  p._showTag = function() {
    this._tag.style.visibility = this._startTagVisibility;
  };

  /**
   * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio
   * that is already in a load, but not complete.
   * @method _handleStalled
   * @private
   */
  p._handleStalled = function () {
    //Ignore, let the timeout take care of it. Sometimes its not really stopped.
  };

  createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest");

}());

//##############################################################################
// MediaTagRequest.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio.
   * @class MediaTagRequest
   * @param {LoadItem} loadItem
   * @param {HTMLAudioElement|HTMLVideoElement} tag
   * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc.
   * @constructor
   */
  function MediaTagRequest(loadItem, tag, srcAttribute) {
    this.AbstractRequest_constructor(loadItem);

    // protected properties
    this._tag = tag;
    this._tagSrcAttribute = srcAttribute;
    this._loadedHandler = createjs.proxy(this._handleTagComplete, this);
  };

  var p = createjs.extend(MediaTagRequest, createjs.TagRequest);
  var s = MediaTagRequest;

  // public methods
  p.load = function () {
    var sc = createjs.proxy(this._handleStalled, this);
    this._stalledCallback = sc;

    var pc = createjs.proxy(this._handleProgress, this);
    this._handleProgress = pc;

    this._tag.addEventListener("stalled", sc);
    this._tag.addEventListener("progress", pc);

    // This will tell us when audio is buffered enough to play through, but not when its loaded.
    // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient.
    this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event.

    this.TagRequest_load();
  };

  // private methods
  p._handleReadyStateChange = function () {
    clearTimeout(this._loadTimeout);
    // This is strictly for tags in browsers that do not support onload.
    var tag = this._tag;

    // Complete is for old IE support.
    if (tag.readyState == "loaded" || tag.readyState == "complete") {
      this._handleTagComplete();
    }
  };

  p._handleStalled = function () {
    //Ignore, let the timeout take care of it. Sometimes its not really stopped.
  };

  /**
   * An XHR request has reported progress.
   * @method _handleProgress
   * @param {Object} event The XHR progress event.
   * @private
   */
  p._handleProgress = function (event) {
    if (!event || event.loaded > 0 && event.total == 0) {
      return; // Sometimes we get no "total", so just ignore the progress event.
    }

    var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
    this.dispatchEvent(newEvent);
  };

  // protected methods
  p._clean = function () {
    this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler);
    this._tag.removeEventListener("stalled", this._stalledCallback);
    this._tag.removeEventListener("progress", this._progressCallback);

    this.TagRequest__clean();
  };

  createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest");

}());

//##############################################################################
// XHRRequest.js
//##############################################################################

(function () {
  "use strict";

// constructor
  /**
   * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used
   * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary.
   * XHR requests load the content as text or binary data, provide progress and consistent completion events, and
   * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for
   * cross-domain loading.
   * @class XHRRequest
   * @constructor
   * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
   * for an overview of supported file properties.
   * @extends AbstractLoader
   */
  function XHRRequest (item) {
    this.AbstractRequest_constructor(item);

    // protected properties
    /**
     * A reference to the XHR request used to load the content.
     * @property _request
     * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP}
     * @private
     */
    this._request = null;

    /**
     * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1,
     * typically IE9).
     * @property _loadTimeout
     * @type {Number}
     * @private
     */
    this._loadTimeout = null;

    /**
     * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect
     * the version, so we use capabilities to make a best guess.
     * @property _xhrLevel
     * @type {Number}
     * @default 1
     * @private
     */
    this._xhrLevel = 1;

    /**
     * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be
     * null until the file is loaded.
     * @property _response
     * @type {mixed}
     * @private
     */
    this._response = null;

    /**
     * The response of the loaded file before it is modified. In most cases, content is converted from raw text to
     * an HTML tag or a formatted object which is set to the <code>result</code> property, but the developer may still
     * want to access the raw content as it was loaded.
     * @property _rawResponse
     * @type {String|Object}
     * @private
     */
    this._rawResponse = null;

    this._canceled = false;

    // Setup our event handlers now.
    this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this);
    this._handleProgressProxy = createjs.proxy(this._handleProgress, this);
    this._handleAbortProxy = createjs.proxy(this._handleAbort, this);
    this._handleErrorProxy = createjs.proxy(this._handleError, this);
    this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this);
    this._handleLoadProxy = createjs.proxy(this._handleLoad, this);
    this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this);

    if (!this._createXHR(item)) {
      //TODO: Throw error?
    }
  };

  var p = createjs.extend(XHRRequest, createjs.AbstractRequest);

// static properties
  /**
   * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE.
   * @property ACTIVEX_VERSIONS
   * @type {Array}
   * @since 0.4.2
   * @private
   */
  XHRRequest.ACTIVEX_VERSIONS = [
    "Msxml2.XMLHTTP.6.0",
    "Msxml2.XMLHTTP.5.0",
    "Msxml2.XMLHTTP.4.0",
    "MSXML2.XMLHTTP.3.0",
    "MSXML2.XMLHTTP",
    "Microsoft.XMLHTTP"
  ];

// Public methods
  /**
   * Look up the loaded result.
   * @method getResult
   * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content
   * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
   * returned instead.
   * @return {Object} A result object containing the content that was loaded, such as:
   * <ul>
   *      <li>An image tag (&lt;image /&gt;) for images</li>
   *      <li>A script tag for JavaScript (&lt;script /&gt;). Note that scripts loaded with tags may be added to the
   *      HTML head.</li>
   *      <li>A style tag for CSS (&lt;style /&gt;)</li>
   *      <li>Raw text for TEXT</li>
   *      <li>A formatted JavaScript object defined by JSON</li>
   *      <li>An XML document</li>
   *      <li>An binary arraybuffer loaded by XHR</li>
   * </ul>
   * Note that if a raw result is requested, but not found, the result will be returned instead.
   */
  p.getResult = function (raw) {
    if (raw && this._rawResponse) {
      return this._rawResponse;
    }
    return this._response;
  };

  // Overrides abstract method in AbstractRequest
  p.cancel = function () {
    this.canceled = true;
    this._clean();
    this._request.abort();
  };

  // Overrides abstract method in AbstractLoader
  p.load = function () {
    if (this._request == null) {
      this._handleError();
      return;
    }

    //Events
    if (this._request.addEventListener != null) {
      this._request.addEventListener("loadstart", this._handleLoadStartProxy, false);
      this._request.addEventListener("progress", this._handleProgressProxy, false);
      this._request.addEventListener("abort", this._handleAbortProxy, false);
      this._request.addEventListener("error", this._handleErrorProxy, false);
      this._request.addEventListener("timeout", this._handleTimeoutProxy, false);

      // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
      this._request.addEventListener("load", this._handleLoadProxy, false);
      this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false);
    } else {
      // IE9 support
      this._request.onloadstart = this._handleLoadStartProxy;
      this._request.onprogress = this._handleProgressProxy;
      this._request.onabort = this._handleAbortProxy;
      this._request.onerror = this._handleErrorProxy;
      this._request.ontimeout = this._handleTimeoutProxy;

      // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these.
      this._request.onload = this._handleLoadProxy;
      this._request.onreadystatechange = this._handleReadyStateChangeProxy;
    }

    // Set up a timeout if we don't have XHR2
    if (this._xhrLevel == 1) {
      this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);
    }

    // Sometimes we get back 404s immediately, particularly when there is a cross origin request.  // note this does not catch in Chrome
    try {
      if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) {
        this._request.send();
      } else if (this._item.method == createjs.AbstractLoader.POST) {
        this._request.send(createjs.RequestUtils.formatQueryString(this._item.values));
      }
    } catch (error) {
      this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error));
    }
  };

  p.setResponseType = function (type) {
    // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded
    if (type === 'blob') {
      type = window.URL ? 'blob' : 'arraybuffer';
      this._responseType = type;
    }
    this._request.responseType = type;
  };

  /**
   * Get all the response headers from the XmlHttpRequest.
   *
   * <strong>From the docs:</strong> Return all the HTTP headers, excluding headers that are a case-insensitive match
   * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair,
   * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE
   * pair.
   * @method getAllResponseHeaders
   * @return {String}
   * @since 0.4.1
   */
  p.getAllResponseHeaders = function () {
    if (this._request.getAllResponseHeaders instanceof Function) {
      return this._request.getAllResponseHeaders();
    } else {
      return null;
    }
  };

  /**
   * Get a specific response header from the XmlHttpRequest.
   *
   * <strong>From the docs:</strong> Returns the header field value from the response of which the field name matches
   * header, unless the field name is Set-Cookie or Set-Cookie2.
   * @method getResponseHeader
   * @param {String} header The header name to retrieve.
   * @return {String}
   * @since 0.4.1
   */
  p.getResponseHeader = function (header) {
    if (this._request.getResponseHeader instanceof Function) {
      return this._request.getResponseHeader(header);
    } else {
      return null;
    }
  };

// protected methods
  /**
   * The XHR request has reported progress.
   * @method _handleProgress
   * @param {Object} event The XHR progress event.
   * @private
   */
  p._handleProgress = function (event) {
    if (!event || event.loaded > 0 && event.total == 0) {
      return; // Sometimes we get no "total", so just ignore the progress event.
    }

    var newEvent = new createjs.ProgressEvent(event.loaded, event.total);
    this.dispatchEvent(newEvent);
  };

  /**
   * The XHR request has reported a load start.
   * @method _handleLoadStart
   * @param {Object} event The XHR loadStart event.
   * @private
   */
  p._handleLoadStart = function (event) {
    clearTimeout(this._loadTimeout);
    this.dispatchEvent("loadstart");
  };

  /**
   * The XHR request has reported an abort event.
   * @method handleAbort
   * @param {Object} event The XHR abort event.
   * @private
   */
  p._handleAbort = function (event) {
    this._clean();
    this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event));
  };

  /**
   * The XHR request has reported an error event.
   * @method _handleError
   * @param {Object} event The XHR error event.
   * @private
   */
  p._handleError = function (event) {
    this._clean();
    this.dispatchEvent(new createjs.ErrorEvent(event.message));
  };

  /**
   * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload
   * event, so we must monitor the readyStateChange to determine if the file is loaded.
   * @method _handleReadyStateChange
   * @param {Object} event The XHR readyStateChange event.
   * @private
   */
  p._handleReadyStateChange = function (event) {
    if (this._request.readyState == 4) {
      this._handleLoad();
    }
  };

  /**
   * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has
   * <code>request.readyState == 4</code>. Only the first call to this method will be processed.
   * @method _handleLoad
   * @param {Object} event The XHR load event.
   * @private
   */
  p._handleLoad = function (event) {
    if (this.loaded) {
      return;
    }
    this.loaded = true;

    var error = this._checkError();
    if (error) {
      this._handleError(error);
      return;
    }

    this._response = this._getResponse();
    // Convert arraybuffer back to blob
    if (this._responseType === 'arraybuffer') {
      try {
        this._response = new Blob([this._response]);
      } catch (e) {
        // Fallback to use BlobBuilder if Blob constructor is not supported
        // Tested on Android 2.3 ~ 4.2 and iOS5 safari
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        if (e.name === 'TypeError' && window.BlobBuilder) {
          var builder = new BlobBuilder();
          builder.append(this._response);
          this._response = builder.getBlob();
        }
      }
    }
    this._clean();

    this.dispatchEvent(new createjs.Event("complete"));
  };

  /**
   * The XHR request has timed out. This is called by the XHR request directly, or via a <code>setTimeout</code>
   * callback.
   * @method _handleTimeout
   * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout.
   * @private
   */
  p._handleTimeout = function (event) {
    this._clean();

    this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event));
  };

// Protected
  /**
   * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note
   * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code.
   * @method _checkError
   * @return {int} If the request status returns an error code.
   * @private
   */
  p._checkError = function () {
    //LM: Probably need additional handlers here, maybe 501
    var status = parseInt(this._request.status);

    switch (status) {
      case 404:   // Not Found
      case 0:     // Not Loaded
        return new Error(status);
    }
    return null;
  };

  /**
   * Validate the response. Different browsers have different approaches, some of which throw errors when accessed
   * in other browsers. If there is no response, the <code>_response</code> property will remain null.
   * @method _getResponse
   * @private
   */
  p._getResponse = function () {
    if (this._response != null) {
      return this._response;
    }

    if (this._request.response != null) {
      return this._request.response;
    }

    // Android 2.2 uses .responseText
    try {
      if (this._request.responseText != null) {
        return this._request.responseText;
      }
    } catch (e) {
    }

    // When loading XML, IE9 does not return .response, instead it returns responseXML.xml
    try {
      if (this._request.responseXML != null) {
        return this._request.responseXML;
      }
    } catch (e) {
    }

    return null;
  };

  /**
   * Create an XHR request. Depending on a number of factors, we get totally different results.
   * <ol><li>Some browsers get an <code>XDomainRequest</code> when loading cross-domain.</li>
   *      <li>XMLHttpRequest are created when available.</li>
   *      <li>ActiveX.XMLHTTP objects are used in older IE browsers.</li>
   *      <li>Text requests override the mime type if possible</li>
   *      <li>Origin headers are sent for crossdomain requests in some browsers.</li>
   *      <li>Binary loads set the response type to "arraybuffer"</li></ol>
   * @method _createXHR
   * @param {Object} item The requested item that is being loaded.
   * @return {Boolean} If an XHR request or equivalent was successfully created.
   * @private
   */
  p._createXHR = function (item) {
    // Check for cross-domain loads. We can't fully support them, but we can try.
    var crossdomain = createjs.RequestUtils.isCrossDomain(item);
    var headers = {};

    // Create the request. Fallback to whatever support we have.
    var req = null;
    if (window.XMLHttpRequest) {
      req = new XMLHttpRequest();
      // This is 8 or 9, so use XDomainRequest instead.
      if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) {
        req = new XDomainRequest();
      }
    } else { // Old IE versions use a different approach
      for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) {
        var axVersion = s.ACTIVEX_VERSIONS[i];
        try {
          req = new ActiveXObject(axVersion);
          break;
        } catch (e) {
        }
      }
      if (req == null) {
        return false;
      }
    }

    // Default to utf-8 for Text requests.
    if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) {
      item.mimeType = "text/plain; charset=utf-8";
    }

    // IE9 doesn't support overrideMimeType(), so we need to check for it.
    if (item.mimeType && req.overrideMimeType) {
      req.overrideMimeType(item.mimeType);
    }

    // Determine the XHR level
    this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1;

    var src = null;
    if (item.method == createjs.AbstractLoader.GET) {
      src = createjs.RequestUtils.buildPath(item.src, item.values);
    } else {
      src = item.src;
    }

    // Open the request.  Set cross-domain flags if it is supported (XHR level 1 only)
    req.open(item.method || createjs.AbstractLoader.GET, src, true);

    if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) {
      headers["Origin"] = location.origin;
    }

    // To send data we need to set the Content-type header)
    if (item.values && item.method == createjs.AbstractLoader.POST) {
      headers["Content-Type"] = "application/x-www-form-urlencoded";
    }

    if (!crossdomain && !headers["X-Requested-With"]) {
      headers["X-Requested-With"] = "XMLHttpRequest";
    }

    if (item.headers) {
      for (var n in item.headers) {
        headers[n] = item.headers[n];
      }
    }

    for (n in headers) {
      req.setRequestHeader(n, headers[n])
    }

    if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) {
      req.withCredentials = item.withCredentials;
    }

    this._request = req;

    return true;
  };

  /**
   * A request has completed (or failed or canceled), and needs to be disposed.
   * @method _clean
   * @private
   */
  p._clean = function () {
    clearTimeout(this._loadTimeout);

    if (this._request.removeEventListener != null) {
      this._request.removeEventListener("loadstart", this._handleLoadStartProxy);
      this._request.removeEventListener("progress", this._handleProgressProxy);
      this._request.removeEventListener("abort", this._handleAbortProxy);
      this._request.removeEventListener("error", this._handleErrorProxy);
      this._request.removeEventListener("timeout", this._handleTimeoutProxy);
      this._request.removeEventListener("load", this._handleLoadProxy);
      this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy);
    } else {
      this._request.onloadstart = null;
      this._request.onprogress = null;
      this._request.onabort = null;
      this._request.onerror = null;
      this._request.ontimeout = null;
      this._request.onload = null;
      this._request.onreadystatechange = null;
    }
  };

  p.toString = function () {
    return "[PreloadJS XHRRequest]";
  };

  createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest");

}());

//##############################################################################
// LoadQueue.js
//##############################################################################

/*
 TODO: WINDOWS ISSUES
 * No error for HTML audio in IE 678
 * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR
 * No script complete handler in IE 67 TAGS (XHR is fine)
 * No XML/JSON in IE6 TAGS
 * Need to hide loading SVG in Opera TAGS
 * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking)
 * SVG no load or failure in Opera XHR
 * Reported issues with IE7/8
 */

(function () {
  "use strict";

// constructor
  /**
   * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either
   * a single file, or queue of files.
   *
   * <b>Creating a Queue</b><br />
   * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR
   * argument to false.
   *
   *      var queue = new createjs.LoadQueue(true);
   *
   * <b>Listening for Events</b><br />
   * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}}
   * lets you add as many listeners as you want for events. You can subscribe to the following events:<ul>
   *     <li>{{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all
   *     files</li>
   *     <li>{{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with
   *     any file.</li>
   *     <li>{{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has
   *     changed.</li>
   *     <li>{{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.</li>
   *     <li>{{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note
   *     that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.</li>
   * </ul>
   *
   *      queue.on("fileload", handleFileLoad, this);
   *      queue.on("complete", handleComplete, this);
   *
   * <b>Adding files and manifests</b><br />
   * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a
   * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are
   * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you
   * like.
   *
   *      queue.loadFile("filePath/file.jpg");
   *      queue.loadFile({id:"image", src:"filePath/file.jpg"});
   *      queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]);
   *
   *      // Use an external manifest
   *      queue.loadManifest("path/to/manifest.json");
   *      queue.loadManifest({src:"manifest.json", type:"manifest"});
   *
   * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not
   * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin
   * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a
   * `loadNow` argument of `true`.
   *
   *      queue.load();
   *
   * <b>File Types</b><br />
   * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS
   * should handle the majority of standard file and url formats, and works with common file extensions. If you have
   * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a
   * <code>type</code> property with any manifest item.
   *
   *      queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.AbstractLoader.SOUND});
   *
   *      // Note that PreloadJS will not read a file extension from the query string
   *      queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.AbstractLoader.IMAGE});
   *
   * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include:
   * <ul>
   *     <li>{{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR</li>
   *     <li>{{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files</li>
   *     <li>{{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats</li>
   *     <li>{{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files</li>
   *     <li>{{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data</li>
   *     <li>{{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain</li>
   *     <li>{{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see
   *     {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}</li>
   *     <li>{{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats</li>
   *     <li>{{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definiteions. This
   *     will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.</li>
   *     <li>{{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files</li>
   *     <li>{{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only</li>
   *     <li>{{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data</li>
   * </ul>
   *
   * <em>Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better
   * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but
   * are deprecated.</em>
   *
   * <b>Handling Results</b><br />
   * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is
   * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a
   * formatted object that can be used immediately, including:
   * <ul>
   *     <li>Binary: The binary loaded result</li>
   *     <li>CSS: A &lt;link /&gt; tag</li>
   *     <li>Image: An &lt;img /&gt; tag</li>
   *     <li>JavaScript: A &lt;script /&gt; tag</li>
   *     <li>JSON/JSONP: A formatted JavaScript Object</li>
   *     <li>Manifest: A JavaScript object.
   *     <li>Sound: An &lt;audio /&gt; tag</a>
   *     <li>SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images.
   *     <li>SVG: An &lt;object /&gt; tag</li>
   *     <li>Text: Raw text</li>
   *     <li>XML: An XML DOM node</li>
   * </ul>
   *
   *      function handleFileLoad(event) {
   *          var item = event.item; // A reference to the item that was passed in to the LoadQueue
   *          var type = item.type;
   *
   *          // Add any images to the page body.
   *          if (type == createjs.LoadQueue.IMAGE) {
   *              document.body.appendChild(event.result);
   *          }
   *      }
   *
   * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up
   * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the
   * "src" or file path can be used instead, including the `path` defined by a manifest, but <strong>not including</strong>
   * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content.
   *
   *      var image = queue.getResult("image");
   *      document.body.appendChild(image);
   *
   * Raw loaded content can be accessed using the <code>rawResult</code> property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
   * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd
   * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript,
   * CSS, XML, SVG, and JSON objects, or anything loaded with XHR.
   *
   *      var image = queue.getResult("image", true); // load the binary image data loaded with XHR.
   *
   * <b>Plugins</b><br />
   * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio,
   * make sure to install the <a href="http://soundjs.com">SoundJS</a> Sound class, which will help load HTML audio,
   * Flash audio, and WebAudio files. This should be installed <strong>before</strong> loading any audio files.
   *
   *      queue.installPlugin(createjs.Sound);
   *
   * <h4>Known Browser Issues</h4>
   * <ul>
   *     <li>Browsers without audio support can not load audio files.</li>
   *     <li>Safari on Mac OS X can only play HTML audio if QuickTime is installed</li>
   *     <li>HTML Audio tags will only download until their <code>canPlayThrough</code> event is fired. Browsers other
   *     than Chrome will continue to download in the background.</li>
   *     <li>When loading scripts using tags, they are automatically added to the document.</li>
   *     <li>Scripts loaded via XHR may not be properly inspectable with browser tools.</li>
   *     <li>IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require
   *     XHR to work.</li>
   *     <li>Content loaded via tags will not show progress, and will continue to download in the background when
   *     canceled, although no events will be dispatched.</li>
   * </ul>
   *
   * @class LoadQueue
   * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP
   * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR
   * when necessary.
   * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue
   * before they are loaded.  Sources beginning with a protocol such as `http://` or a relative path such as `../`
   * will not receive a base path.
   * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To
   * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any
   * string value will be passed through, but only "" and "Anonymous" are recommended. <strong>Note: The crossOrigin
   * parameter is deprecated. Use LoadItem.crossOrigin instead</strong>
   *
   * @constructor
   * @extends AbstractLoader
   */
  function LoadQueue (preferXHR, basePath, crossOrigin) {
    this.AbstractLoader_constructor();

    /**
     * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}.
     * @property _plugins
     * @type {Array}
     * @private
     * @since 0.6.1
     */
    this._plugins = [];

    /**
     * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the
     * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
     * method for more information.
     * @property _typeCallbacks
     * @type {Object}
     * @private
     */
    this._typeCallbacks = {};

    /**
     * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the
     * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}
     * method for more information.
     * @property _extensionCallbacks
     * @type {null}
     * @private
     */
    this._extensionCallbacks = {};

    /**
     * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and
     * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed.
     * @property next
     * @type {LoadQueue}
     * @default null
     */
    this.next = null;

    /**
     * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head
     * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas
     * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order
     * specified.
     *
     * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}}
     * property on the load item, or by ensuring that only one connection can be open at a time using
     * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property
     * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the
     * `maintainScriptOrder` to `false` during a load will not change items already in a queue.
     *
     * <h4>Example</h4>
     *
     *      var queue = new createjs.LoadQueue();
     *      queue.setMaxConnections(3); // Set a higher number to load multiple items at once
     *      queue.maintainScriptOrder = true; // Ensure scripts are loaded in order
     *      queue.loadManifest([
     *          "script1.js",
     *          "script2.js",
     *          "image.png", // Load any time
     *          {src: "image2.png", maintainOrder: true} // Will wait for script2.js
     *          "image3.png",
     *          "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR)
     *      ]);
     *
     * @property maintainScriptOrder
     * @type {Boolean}
     * @default true
     */
    this.maintainScriptOrder = true;

    /**
     * Determines if the LoadQueue will stop processing the current queue when an error is encountered.
     * @property stopOnError
     * @type {Boolean}
     * @default false
     */
    this.stopOnError = false;

    /**
     * The number of maximum open connections that a loadQueue tries to maintain. Please see
     * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information.
     * @property _maxConnections
     * @type {Number}
     * @default 1
     * @private
     */
    this._maxConnections = 1;

    /**
     * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the
     * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can
     * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is
     * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the
     * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of
     * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}.
     *
     * Loaders can be removed from PreloadJS by simply not including them.
     *
     * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list
     * so that they are checked first.
     * @property _availableLoaders
     * @type {Array}
     * @private
     * @since 0.6.0
     */
    this._availableLoaders = [
      createjs.ImageLoader,
      createjs.JavaScriptLoader,
      createjs.CSSLoader,
      createjs.JSONLoader,
      createjs.JSONPLoader,
      createjs.SoundLoader,
      createjs.ManifestLoader,
      createjs.SpriteSheetLoader,
      createjs.XMLLoader,
      createjs.SVGLoader,
      createjs.BinaryLoader,
      createjs.VideoLoader,
      createjs.TextLoader,
    ];

    /**
     * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}.
         * @property _defaultLoaderLength
     * @type {Number}
     * @private
     * @since 0.6.0
     */
    this._defaultLoaderLength = this._availableLoaders.length;

    this.init(preferXHR, basePath, crossOrigin);
  }

  var p = createjs.extend(LoadQueue, createjs.AbstractLoader);
  var s = LoadQueue;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.

  /**
   * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue.
   * @method init
   * @param preferXHR
   * @param basePath
   * @param crossOrigin
   * @private
   */
  p.init = function (preferXHR, basePath, crossOrigin) {

    // public properties
    /**
     * @property useXHR
     * @type {Boolean}
     * @readonly
     * @default true
     * @deprecated Use preferXHR instead.
     */
    this.useXHR = true;

    /**
     * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR
     * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR,
     * and plain text can not be loaded with tags, so it will default the the correct type instead of using the
     * user-defined type.
     * @type {Boolean}
     * @default true
     * @since 0.6.0
     */
    this.preferXHR = true; //TODO: Get/Set
    this._preferXHR = true;
    this.setPreferXHR(preferXHR);

    // protected properties
    /**
     * Whether the queue is currently paused or not.
     * @property _paused
     * @type {boolean}
     * @private
     */
    this._paused = false;

    /**
     * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The
     * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such
     * as `http://`, or a relative path such as `../`.
     * @property _basePath
     * @type {String}
     * @private
     * @since 0.3.1
     */
    this._basePath = basePath;

    /**
     * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded
     * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by
     * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues,
     * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are ""
     * and "Anonymous".
     * @property _crossOrigin
     * @type {String}
     * @default ""
     * @private
     * @since 0.4.1
     */
    this._crossOrigin = crossOrigin;

    /**
     * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first
     * file is requested.
     * @property _loadStartWasDispatched
     * @type {Boolean}
     * @default false
     * @private
     */
    this._loadStartWasDispatched = false;

    /**
     * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when
     * using a script tag to do preloading.
     * @property _currentlyLoadingScript
     * @type {Boolean}
     * @private
     */
    this._currentlyLoadingScript = null;

    /**
     * An array containing the currently downloading files.
     * @property _currentLoads
     * @type {Array}
     * @private
     */
    this._currentLoads = [];

    /**
     * An array containing the queued items that have not yet started downloading.
     * @property _loadQueue
     * @type {Array}
     * @private
     */
    this._loadQueue = [];

    /**
     * An array containing downloads that have not completed, so that the LoadQueue can be properly reset.
     * @property _loadQueueBackup
     * @type {Array}
     * @private
     */
    this._loadQueueBackup = [];

    /**
     * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}}
     * id.
     * @property _loadItemsById
     * @type {Object}
     * @private
     */
    this._loadItemsById = {};

    /**
     * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}}
     * source.
     * @property _loadItemsBySrc
     * @type {Object}
     * @private
     */
    this._loadItemsBySrc = {};

    /**
     * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
     * @property _loadedResults
     * @type {Object}
     * @private
     */
    this._loadedResults = {};

    /**
     * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}.
     * @property _loadedRawResults
     * @type {Object}
     * @private
     */
    this._loadedRawResults = {};

    /**
     * The number of items that have been requested. This helps manage an overall progress without knowing how large
     * the files are before they are downloaded. This does not include items inside of loaders such as the
     * {{#crossLink "ManifestLoader"}}{{/crossLink}}.
     * @property _numItems
     * @type {Number}
     * @default 0
     * @private
     */
    this._numItems = 0;

    /**
     * The number of items that have completed loaded. This helps manage an overall progress without knowing how large
     * the files are before they are downloaded.
     * @property _numItemsLoaded
     * @type {Number}
     * @default 0
     * @private
     */
    this._numItemsLoaded = 0;

    /**
     * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right
     * order.
     * @property _scriptOrder
     * @type {Array}
     * @private
     */
    this._scriptOrder = [];

    /**
     * A list of scripts that have been loaded. Items are added to this list as <code>null</code> when they are
     * requested, contain the loaded item if it has completed, but not been dispatched to the user, and <code>true</true>
     * once they are complete and have been dispatched.
     * @property _loadedScripts
     * @type {Array}
     * @private
     */
    this._loadedScripts = [];

    /**
     * The last progress amount. This is used to suppress duplicate progress events.
     * @property _lastProgress
     * @type {Number}
     * @private
     * @since 0.6.0
     */
    this._lastProgress = NaN;

  };

// static properties
  /**
   * The time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}
   * event is dispatched if the timeout is reached before any data is received.
   * @property loadTimeout
   * @type {Number}
   * @default 8000
   * @static
   * @since 0.4.1
   * @deprecated In favour of {{#crossLink "LoadItem/LOAD_TIMEOUT_DEFAULT:property}}{{/crossLink}} property.
   */
  s.loadTimeout = 8000;

  /**
   * The time in milliseconds to assume a load has failed.
   * @property LOAD_TIMEOUT
   * @type {Number}
   * @default 0
   * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property.
   */
  s.LOAD_TIMEOUT = 0;

// Preload Types
  /**
   * @property BINARY
   * @type {String}
   * @default binary
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} instead.
   */
  s.BINARY = createjs.AbstractLoader.BINARY;

  /**
   * @property CSS
   * @type {String}
   * @default css
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
   */
  s.CSS = createjs.AbstractLoader.CSS;

  /**
   * @property IMAGE
   * @type {String}
   * @default image
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}} instead.
   */
  s.IMAGE = createjs.AbstractLoader.IMAGE;

  /**
   * @property JAVASCRIPT
   * @type {String}
   * @default javascript
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
   */
  s.JAVASCRIPT = createjs.AbstractLoader.JAVASCRIPT;

  /**
   * @property JSON
   * @type {String}
   * @default json
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}} instead.
   */
  s.JSON = createjs.AbstractLoader.JSON;

  /**
   * @property JSONP
   * @type {String}
   * @default jsonp
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}} instead.
   */
  s.JSONP = createjs.AbstractLoader.JSONP;

  /**
   * @property MANIFEST
   * @type {String}
   * @default manifest
   * @static
   * @since 0.4.1
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} instead.
   */
  s.MANIFEST = createjs.AbstractLoader.MANIFEST;

  /**
   * @property SOUND
   * @type {String}
   * @default sound
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
   */
  s.SOUND = createjs.AbstractLoader.SOUND;

  /**
   * @property VIDEO
   * @type {String}
   * @default video
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} instead.
   */
  s.VIDEO = createjs.AbstractLoader.VIDEO;

  /**
   * @property SVG
   * @type {String}
   * @default svg
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} instead.
   */
  s.SVG = createjs.AbstractLoader.SVG;

  /**
   * @property TEXT
   * @type {String}
   * @default text
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}} instead.
   */
  s.TEXT = createjs.AbstractLoader.TEXT;

  /**
   * @property XML
   * @type {String}
   * @default xml
   * @static
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}} instead.
   */
  s.XML = createjs.AbstractLoader.XML;

  /**
   * @property POST
   * @type {string}
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} instead.
   */
  s.POST = createjs.AbstractLoader.POST;

  /**
   * @property GET
   * @type {string}
   * @deprecated Use the AbstractLoader {{#crossLink "AbstractLoader/GET:property"}}{{/crossLink}} instead.
   */
  s.GET = createjs.AbstractLoader.GET;

// events
  /**
   * This event is fired when an individual file has loaded, and been processed.
   * @event fileload
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
   * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
   * object will contain that value as a `src` property.
   * @param {Object} result The HTML tag or parsed result of the loaded item.
   * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted
   * to a usable object.
   * @since 0.3.0
   */

  /**
   * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes.
   * @event fileprogress
   * @since 0.3.0
   */

  /**
   * This event is fired when an individual file starts to load.
   * @event filestart
   * @param {Object} The object that dispatched the event.
   * @param {String} type The event type.
   * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
   * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the
   * object will contain that value as a property.
   */

// public methods
  /**
   * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders.
   * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added
   * once, and will be prepended to the list of available loaders.
   * @method registerLoader
   * @param {Function|AbstractLoader} loader The AbstractLoader class to add.
   * @since 0.6.0
   */
  p.registerLoader = function (loader) {
    if (!loader || !loader.canLoadItem) {
      throw new Error("loader is of an incorrect type.");
    } else if (this._availableLoaders.indexOf(loader) != -1) {
      throw new Error("loader already exists."); //LM: Maybe just silently fail here
    }

    this._availableLoaders.unshift(loader);
  };

  /**
   * Remove a custom loader added usig {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be
   * unregistered, the default loaders will always be available.
   * @method unregisterLoader
   * @param {Function|AbstractLoader} loader The AbstractLoader class to remove
   */
  p.unregisterLoader = function (loader) {
    var idx = this._availableLoaders.indexOf(loader);
    if (idx != -1 && idx < this._defaultLoaderLength - 1) {
      this._availableLoaders.splice(idx, 1);
    }
  };

  /**
   * @method setUseXHR
   * @param {Boolean} value The new useXHR value to set.
   * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if
   * the provided value argument was true.
   * @since 0.3.0
   * @deprecated use the {{#crossLink "preferXHR:property"}}{{/crossLink}} property, or the {{#crossLink "setUseXHR"}}{{/crossLink}}
   * method instead.
   */
  p.setUseXHR = function (value) {
    return this.setPreferXHR(value);
  };

  /**
   * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may
   * fail, or be ignored depending on the browser's capabilities and the load type.
   * @method setPreferXHR
   * @param {Boolean} value
   * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set.
   * @since 0.6.0
   */
  p.setPreferXHR = function (value) {
    // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it.
    //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR.
    this.preferXHR = (value != false && window.XMLHttpRequest != null);
    return this.preferXHR;
  };

  /**
   * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded
   * content, and allows the queue to be used again.
   * @method removeAll
   * @since 0.3.0
   */
  p.removeAll = function () {
    this.remove();
  };

  /**
   * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed.
   * This also removes internal references to loaded item(s).
   *
   * <h4>Example</h4>
   *
   *      queue.loadManifest([
   *          {src:"test.png", id:"png"},
   *          {src:"test.jpg", id:"jpg"},
   *          {src:"test.mp3", id:"mp3"}
   *      ]);
   *      queue.remove("png"); // Single item by ID
   *      queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src.
   *      queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src.
   *
   * @method remove
   * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of
   * items, or multiple items as arguments.
   * @since 0.3.0
   */
  p.remove = function (idsOrUrls) {
    var args = null;

    if (idsOrUrls && !(idsOrUrls instanceof Array)) {
      args = [idsOrUrls];
    } else if (idsOrUrls) {
      args = idsOrUrls;
    } else if (arguments.length > 0) {
      return;
    }

    var itemsWereRemoved = false;

    // Destroy everything
    if (!args) {
      this.close();
      for (var n in this._loadItemsById) {
        this._disposeItem(this._loadItemsById[n]);
      }
      this.init(this.preferXHR, this._basePath);

      // Remove specific items
    } else {
      while (args.length) {
        var item = args.pop();
        var r = this.getResult(item);

        //Remove from the main load Queue
        for (i = this._loadQueue.length - 1; i >= 0; i--) {
          loadItem = this._loadQueue[i].getItem();
          if (loadItem.id == item || loadItem.src == item) {
            this._loadQueue.splice(i, 1)[0].cancel();
            break;
          }
        }

        //Remove from the backup queue
        for (i = this._loadQueueBackup.length - 1; i >= 0; i--) {
          loadItem = this._loadQueueBackup[i].getItem();
          if (loadItem.id == item || loadItem.src == item) {
            this._loadQueueBackup.splice(i, 1)[0].cancel();
            break;
          }
        }

        if (r) {
          this._disposeItem(this.getItem(item));
        } else {
          for (var i = this._currentLoads.length - 1; i >= 0; i--) {
            var loadItem = this._currentLoads[i].getItem();
            if (loadItem.id == item || loadItem.src == item) {
              this._currentLoads.splice(i, 1)[0].cancel();
              itemsWereRemoved = true;
              break;
            }
          }
        }
      }

      // If this was called during a load, try to load the next item.
      if (itemsWereRemoved) {
        this._loadNext();
      }
    }
  };

  /**
   * Stops all open loads, destroys any loaded items, and resets the queue, so all items can
   * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the
   * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or
   * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method.
   * @method reset
   * @since 0.3.0
   */
  p.reset = function () {
    this.close();
    for (var n in this._loadItemsById) {
      this._disposeItem(this._loadItemsById[n]);
    }

    //Reset the queue to its start state
    var a = [];
    for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) {
      a.push(this._loadQueueBackup[i].getItem());
    }

    this.loadManifest(a, false);
  };

  /**
   * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc).
   * Currently, only one plugin can exist per type/extension.
   *
   * When a plugin is installed, a <code>getPreloadHandlers()</code> method will be called on it. For more information
   * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the
   * {{#crossLink "SamplePlugin"}}{{/crossLink}} class.
   *
   * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned
   * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its
   * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when
   * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these
   * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}}
   * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}.
   *
   * @method installPlugin
   * @param {Function} plugin The plugin class to install.
   */
  p.installPlugin = function (plugin) {
    if (plugin == null) {
      return;
    }

    if (plugin.getPreloadHandlers != null) {
      this._plugins.push(plugin);
      var map = plugin.getPreloadHandlers();
      map.scope = plugin;

      if (map.types != null) {
        for (var i = 0, l = map.types.length; i < l; i++) {
          this._typeCallbacks[map.types[i]] = map;
        }
      }

      if (map.extensions != null) {
        for (i = 0, l = map.extensions.length; i < l; i++) {
          this._extensionCallbacks[map.extensions[i]] = map;
        }
      }
    }
  };

  /**
   * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum
   * number of open connections, so any additional connections may remain in a pending state until the browser
   * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}}
   * is `true`, only one script is loaded at a time due to browser limitations.
   *
   * <h4>Example</h4>
   *
   *      var queue = new createjs.LoadQueue();
   *      queue.setMaxConnections(10); // Allow 10 concurrent loads
   *
   * @method setMaxConnections
   * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue
   * is open at any time.
   */
  p.setMaxConnections = function (value) {
    this._maxConnections = value;
    if (!this._paused && this._loadQueue.length > 0) {
      this._loadNext();
    }
  };

  /**
   * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
   * method.
   *
   * Files are always appended to the current queue, so this method can be used multiple times to add files.
   * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
   * @method loadFile
   * @param {LoadItem|Object|String} file The file object or path to load. A file can be either
   * <ul>
   *     <li>A {{#crossLink "LoadItem"}}{{/crossLink}} instance</li>
   *     <li>An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}</li>
   *     <li>OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
   *     in the background.</li>
   * </ul>
   * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
   * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is
   * `true`, the queue will resume automatically.
   * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
   * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}},
   * its files will <strong>NOT</strong> use the basePath parameter. <strong>The basePath parameter is deprecated.</strong>
   * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
   * constructor, or a `path` property in a manifest definition.
   */
  p.loadFile = function (file, loadNow, basePath) {
    if (file == null) {
      var event = new createjs.ErrorEvent("PRELOAD_NO_FILE");
      this._sendError(event);
      return;
    }
    this._addItem(file, null, basePath);

    if (loadNow !== false) {
      this.setPaused(false);
    } else {
      this.setPaused(true);
    }
  };

  /**
   * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method.
   * The files in the manifest are requested in the same order, but may complete in a different order if the max
   * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load
   * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is
   * default).
   *
   * Files are always appended to the current queue, so this method can be used multiple times to add files.
   * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method.
   * @method loadManifest
   * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of
   * manifests:
   * <ol>
   *     <li>A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property,
   *     which defines the list of files to load, and can optionally contain a "path" property, which will be
   *     prepended to each file in the list.</li>
   *     <li>An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP
   *     file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load,
   *     and can optionally contain a "path" property, which will be prepended to each file in the list.</li>
   *     <li>An object which contains a "manifest" property, which defines the list of files to load, and can
   *     optionally contain a "path" property, which will be prepended to each file in the list.</li>
   *     <li>An Array of files to load.</li>
   * </ol>
   *
   * Each "file" in a manifest can be either:
   * <ul>
   *     <li>A {{#crossLink "LoadItem"}}{{/crossLink}} instance</li>
   *     <li>An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}</li>
   *     <li>OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}}
   *     in the background.</li>
   * </ul>
   *
   * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default
   * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is
   * `true`, the queue will resume automatically.
   * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the
   * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}},
   * its files will <strong>NOT</strong> use the basePath parameter. <strong>The basePath parameter is deprecated.</strong>
   * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue
   * constructor, or a `path` property in a manifest definition.
   */
  p.loadManifest = function (manifest, loadNow, basePath) {
    var fileList = null;
    var path = null;

    // Array-based list of items
    if (manifest instanceof Array) {
      if (manifest.length == 0) {
        var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");
        this._sendError(event);
        return;
      }
      fileList = manifest;

      // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded.
    } else if (typeof(manifest) === "string") {
      fileList = [
        {
          src: manifest,
          type: s.MANIFEST
        }
      ];

    } else if (typeof(manifest) == "object") {

      // An object that defines a manifest path
      if (manifest.src !== undefined) {
        if (manifest.type == null) {
          manifest.type = s.MANIFEST;
        } else if (manifest.type != s.MANIFEST) {
          var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");
          this._sendError(event);
        }
        fileList = [manifest];

        // An object that defines a manifest
      } else if (manifest.manifest !== undefined) {
        fileList = manifest.manifest;
        path = manifest.path;
      }

      // Unsupported. This will throw an error.
    } else {
      var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");
      this._sendError(event);
      return;
    }

    for (var i = 0, l = fileList.length; i < l; i++) {
      this._addItem(fileList[i], path, basePath);
    }

    if (loadNow !== false) {
      this.setPaused(false);
    } else {
      this.setPaused(true);
    }

  };

  /**
   * Start a LoadQueue that was created, but not automatically started.
   * @method load
   */
  p.load = function () {
    this.setPaused(false);
  };

  /**
   * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was
   * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
   * `basePath` will not be part of the ID.
   * @method getItem
   * @param {String} value The <code>id</code> or <code>src</code> of the load item.
   * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}
   * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}
   * event as the `item` parameter.
   */
  p.getItem = function (value) {
    return this._loadItemsById[value] || this._loadItemsBySrc[value];
  };

  /**
   * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id"
   * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The
   * `basePath` will not be part of the ID.
   * @method getResult
   * @param {String} value The <code>id</code> or <code>src</code> of the load item.
   * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content
   * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be
   * returned instead.
   * @return {Object} A result object containing the content that was loaded, such as:
   * <ul>
   *      <li>An image tag (&lt;image /&gt;) for images</li>
   *      <li>A script tag for JavaScript (&lt;script /&gt;). Note that scripts are automatically added to the HTML
   *      DOM.</li>
   *      <li>A style tag for CSS (&lt;style /&gt; or &lt;link &gt;)</li>
   *      <li>Raw text for TEXT</li>
   *      <li>A formatted JavaScript object defined by JSON</li>
   *      <li>An XML document</li>
   *      <li>A binary arraybuffer loaded by XHR</li>
   *      <li>An audio tag (&lt;audio &gt;) for HTML audio. Note that it is recommended to use SoundJS APIs to play
   *      loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method
   *      which can not be used to play audio back.</li>
   * </ul>
   * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item`
   * parameter. Note that if a raw result is requested, but not found, the result will be returned instead.
   */
  p.getResult = function (value, rawResult) {
    var item = this._loadItemsById[value] || this._loadItemsBySrc[value];
    if (item == null) {
      return null;
    }
    var id = item.id;
    if (rawResult && this._loadedRawResults[id]) {
      return this._loadedRawResults[id];
    }
    return this._loadedResults[id];
  };

  /**
   * Generate an list of items loaded by this queue.
   * @method getItems
   * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress
   * and failed load items will also be included.
   * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}},
   * result, and rawResult.
   * @since 0.6.0
   */
  p.getItems = function (loaded) {
    var arr = [];
    for (var n in this._loadItemsById) {
      var item = this._loadItemsById[n];
      var result = this.getResult(n);
      if (loaded === true && result == null) {
        continue;
      }
      arr.push({
        item: item,
        result: result,
        rawResult: this.getResult(n, true)
      });
    }
    return arr;
  };

  /**
   * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not
   * be processed when active loads complete. LoadQueues are not paused by default.
   *
   * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or
   * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow`
   * argument is `false`.
   * @method setPaused
   * @param {Boolean} value Whether the queue should be paused or not.
   */
  p.setPaused = function (value) {
    this._paused = value;
    if (!this._paused) {
      this._loadNext();
    }
  };

  /**
   * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from
   * starting to download. Note that currently any active loads will remain open, and events may be processed.
   *
   * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead.
   * @method close
   */
  p.close = function () {
    while (this._currentLoads.length) {
      this._currentLoads.pop().cancel();
    }
    this._scriptOrder.length = 0;
    this._loadedScripts.length = 0;
    this.loadStartWasDispatched = false;
    this._itemCount = 0;
    this._lastProgress = NaN;
  };

// protected methods
  /**
   * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to
   * load the content. The load queue is populated with the loader instance that handles preloading, and not the load
   * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}}
   * method.
   * @method _addItem
   * @param {String|Object} value The item to add to the queue.
   * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is
   * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was
   * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after.
   * @param {String} [basePath] <strong>Deprecated</strong>An optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
   * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged
   * version.
   * @private
   */
  p._addItem = function (value, path, basePath) {
    var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src.
    if (item == null) {
      return;
    } // Sometimes plugins or types should be skipped.
    var loader = this._createLoader(item);
    if (loader != null) {
      if ("plugins" in loader) {
        loader.plugins = this._plugins;
      }
      item._loader = loader;
      this._loadQueue.push(loader);
      this._loadQueueBackup.push(loader);

      this._numItems++;
      this._updateProgress();

      // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time.
      if ((this.maintainScriptOrder
          && item.type == createjs.LoadQueue.JAVASCRIPT
            //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way
          )
          || item.maintainOrder === true) {
        this._scriptOrder.push(item);
        this._loadedScripts.push(null);
      }
    }
  };

  /**
   * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of
   * item is determined by browser support, requirements based on the file type, and developer settings. For example,
   * XHR is only used for file types that support it in new browsers.
   *
   * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may
   * alter the load item.
   * @method _createLoadItem
   * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded.
   * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will
   * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}}
   * when it is added.
   * @param {String} [basePath] <strong>Deprectated</strong> A base path to prepend to the items source in addition to
   * the path argument.
   * @return {Object} The loader instance that will be used.
   * @private
   */
  p._createLoadItem = function (value, path, basePath) {
    var item = createjs.LoadItem.create(value);
    if (item == null) {
      return null;
    }

    var bp = ""; // Store the generated basePath
    var useBasePath = basePath || this._basePath;

    if (item.src instanceof Object) {
      if (!item.type) {
        return null;
      } // the the src is an object, type is required to pass off to plugin
      if (path) {
        bp = path;
        var pathMatch = createjs.RequestUtils.parseURI(path);
        // Also append basePath
        if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
          bp = useBasePath + bp;
        }
      } else if (useBasePath != null) {
        bp = useBasePath;
      }
    } else {
      // Determine Extension, etc.
      var match = createjs.RequestUtils.parseURI(item.src);
      if (match.extension) {
        item.ext = match.extension;
      }
      if (item.type == null) {
        item.type = createjs.RequestUtils.getTypeByExtension(item.ext);
      }

      // Inject path & basePath
      var autoId = item.src;
      if (!match.absolute && !match.relative) {
        if (path) {
          bp = path;
          var pathMatch = createjs.RequestUtils.parseURI(path);
          autoId = path + autoId;
          // Also append basePath
          if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
            bp = useBasePath + bp;
          }
        } else if (useBasePath != null) {
          bp = useBasePath;
        }
      }
      item.src = bp + item.src;
    }
    item.path = bp;

    // If there's no id, set one now.
    if (item.id === undefined || item.id === null || item.id === "") {
      item.id = autoId;
    }

    // Give plugins a chance to modify the loadItem:
    var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext];
    if (customHandler) {
      // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately)
      var result = customHandler.callback.call(customHandler.scope, item, this);

      // The plugin will handle the load, or has canceled it. Ignore it.
      if (result === false) {
        return null;

        // Load as normal:
      } else if (result === true) {
        // Do Nothing

        // Result is a loader class:
      } else if (result != null) {
        item._loader = result;
      }

      // Update the extension in case the type changed:
      match = createjs.RequestUtils.parseURI(item.src);
      if (match.extension != null) {
        item.ext = match.extension;
      }
    }

    // Store the item for lookup. This also helps clean-up later.
    this._loadItemsById[item.id] = item;
    this._loadItemsBySrc[item.src] = item;

    if (item.crossOrigin == null) {
      item.crossOrigin = this._crossOrigin;
    }

    return item;
  };

  /**
   * Create a loader for a load item.
   * @method _createLoader
   * @param {Object} item A formatted load item that can be used to generate a loader.
   * @return {AbstractLoader} A loader that can be used to load content.
   * @private
   */
  p._createLoader = function (item) {
    if (item._loader != null) { // A plugin already specified a loader
      return item._loader;
    }

    // Initially, try and use the provided/supported XHR mode:
    var preferXHR = this.preferXHR;

    for (var i = 0; i < this._availableLoaders.length; i++) {
      var loader = this._availableLoaders[i];
      if (loader && loader.canLoadItem(item)) {
        return new loader(item, preferXHR);
      }
    }

    // TODO: Log error (requires createjs.log)
    return null;
  };

  /**
   * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event
   * is processed. The queue will "fill up" any empty slots, up to the max connection specified using
   * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded
   * using tags, which have to be loaded one at a time to maintain load order.
   * @method _loadNext
   * @private
   */
  p._loadNext = function () {
    if (this._paused) {
      return;
    }

    // Only dispatch loadstart event when the first file is loaded.
    if (!this._loadStartWasDispatched) {
      this._sendLoadStart();
      this._loadStartWasDispatched = true;
    }

    // The queue has completed.
    if (this._numItems == this._numItemsLoaded) {
      this.loaded = true;
      this._sendComplete();

      // Load the next queue, if it has been defined.
      if (this.next && this.next.load) {
        this.next.load();
      }
    } else {
      this.loaded = false;
    }

    // Must iterate forwards to load in the right order.
    for (var i = 0; i < this._loadQueue.length; i++) {
      if (this._currentLoads.length >= this._maxConnections) {
        break;
      }
      var loader = this._loadQueue[i];

      // Determine if we should be only loading one tag-script at a time:
      // Note: maintainOrder items don't do anything here because we can hold onto their loaded value
      if (!this._canStartLoad(loader)) {
        continue;
      }
      this._loadQueue.splice(i, 1);
      i--;
      this._loadItem(loader);
    }
  };

  /**
   * Begin loading an item. Event listeners are not added to the loaders until the load starts.
   * @method _loadItem
   * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader.
   * @private
   */
  p._loadItem = function (loader) {
    loader.on("fileload", this._handleFileLoad, this);
    loader.on("progress", this._handleProgress, this);
    loader.on("complete", this._handleFileComplete, this);
    loader.on("error", this._handleError, this);
    loader.on("fileerror", this._handleFileError, this);
    this._currentLoads.push(loader);
    this._sendFileStart(loader.getItem());
    loader.load();
  };

  /**
   * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}}
   * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}}
   * events.
   * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader.
   * @private
   * @since 0.6.0
   */
  p._handleFileLoad = function (event) {
    event.target = null;
    this.dispatchEvent(event);
  };

  /**
   * The callback that is fired when a loader encounters an error from an internal file load operation. This enables
   * loaders like M
   * @param event
   * @private
   */
  p._handleFileError = function (event) {
    var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item);
    this._sendError(newEvent);
  };

  /**
   * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}}
   * is set to `true`.
   * @method _handleError
   * @param {ErrorEvent} event The error event, containing relevant error information.
   * @private
   */
  p._handleError = function (event) {
    var loader = event.target;
    this._numItemsLoaded++;

    this._finishOrderedItem(loader, true);
    this._updateProgress();

    var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem());
    // TODO: Propagate actual error message.

    this._sendError(newEvent);

    if (!this.stopOnError) {
      this._removeLoadItem(loader);
      this._cleanLoadItem(loader);
      this._loadNext();
    } else {
      this.setPaused(true);
    }
  };

  /**
   * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and
   * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML,
   * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}.
   * @method _handleFileComplete
   * @param {Event} event The event object from the loader.
   * @private
   */
  p._handleFileComplete = function (event) {
    var loader = event.target;
    var item = loader.getItem();

    var result = loader.getResult();
    this._loadedResults[item.id] = result;
    var rawResult = loader.getResult(true);
    if (rawResult != null && rawResult !== result) {
      this._loadedRawResults[item.id] = rawResult;
    }

    this._saveLoadedItems(loader);

    // Remove the load item
    this._removeLoadItem(loader);

    if (!this._finishOrderedItem(loader)) {
      // The item was NOT managed, so process it now
      this._processFinishedLoad(item, loader);
    }

    // Clean up the load item
    this._cleanLoadItem(loader);
  };

  /**
   * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}).
   * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the
   * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}}
   * methods.
   * @method _saveLoadedItems
   * @param {AbstractLoader} loader
   * @protected
   * @since 0.6.0
   */
  p._saveLoadedItems = function (loader) {
    // TODO: Not sure how to handle this. Would be nice to expose the items.
    // Loaders may load sub-items. This adds them to this queue
    var list = loader.getLoadedItems();
    if (list === null) {
      return;
    }

    for (var i = 0; i < list.length; i++) {
      var item = list[i].item;

      // Store item lookups
      this._loadItemsBySrc[item.src] = item;
      this._loadItemsById[item.id] = item;

      // Store loaded content
      this._loadedResults[item.id] = list[i].result;
      this._loadedRawResults[item.id] = list[i].rawResult;
    }
  };

  /**
   * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if
   * so, trigger prior items to trigger as well.
   * @method _finishOrderedItem
   * @param {AbstractLoader} loader
   * @param {Boolean} loadFailed
   * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate
   * behaviour if it is.
   * @private
   */
  p._finishOrderedItem = function (loader, loadFailed) {
    var item = loader.getItem();

    if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT)
        || item.maintainOrder) {

      //TODO: Evaluate removal of the _currentlyLoadingScript
      if (loader instanceof createjs.JavaScriptLoader) {
        this._currentlyLoadingScript = false;
      }

      var index = createjs.indexOf(this._scriptOrder, item);
      if (index == -1) {
        return false;
      } // This loader no longer exists
      this._loadedScripts[index] = (loadFailed === true) ? true : item;

      this._checkScriptLoadOrder();
      return true;
    }

    return false;
  };

  /**
   * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the
   * order they were added, but with a "null" value. When they are completed, the value is set to the load item,
   * and then when they are processed and dispatched, the value is set to `true`. This method simply
   * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are
   * dispatched.
   * @method _checkScriptLoadOrder
   * @private
   */
  p._checkScriptLoadOrder = function () {
    var l = this._loadedScripts.length;

    for (var i = 0; i < l; i++) {
      var item = this._loadedScripts[i];
      if (item === null) {
        break;
      } // This is still loading. Do not process further.
      if (item === true) {
        continue;
      } // This has completed, and been processed. Move on.

      var loadItem = this._loadedResults[item.id];
      if (item.type == createjs.LoadQueue.JAVASCRIPT) {
        // Append script tags to the head automatically.
        createjs.DomUtils.appendToHead(loadItem);
      }

      var loader = item._loader;
      this._processFinishedLoad(item, loader);
      this._loadedScripts[i] = true;
    }
  };

  /**
   * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts
   * the next item.
   * @method _processFinishedLoad
   * @param {LoadItem|Object} item
   * @param {AbstractLoader} loader
   * @protected
   */
  p._processFinishedLoad = function (item, loader) {
    this._numItemsLoaded++;

    // Since LoadQueue needs maintain order, we can't append scripts in the loader.
    // So we do it here instead. Or in _checkScriptLoadOrder();
    if (!this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) {
      createjs.DomUtils.appendToHead(item.result);
    }

    this._updateProgress();
    this._sendFileComplete(item, loader);
    this._loadNext();
  };

  /**
   * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to
   * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed <strong>before</strong>
   * the script can even be started, since it exist in the DOM while loading.
   * @method _canStartLoad
   * @param {AbstractLoader} loader The loader for the item
   * @return {Boolean} Whether the item can start a load or not.
   * @private
   */
  p._canStartLoad = function (loader) {
    if (!this.maintainScriptOrder || loader.preferXHR) {
      return true;
    }
    var item = loader.getItem();
    if (item.type != createjs.LoadQueue.JAVASCRIPT) {
      return true;
    }
    if (this._currentlyLoadingScript) {
      return false;
    }

    var index = this._scriptOrder.indexOf(item);
    var i = 0;
    while (i < index) {
      var checkItem = this._loadedScripts[i];
      if (checkItem == null) {
        return false;
      }
      i++;
    }
    this._currentlyLoadingScript = true;
    return true;
  };

  /**
   * A load item is completed or was canceled, and needs to be removed from the LoadQueue.
   * @method _removeLoadItem
   * @param {AbstractLoader} loader A loader instance to remove.
   * @private
   */
  p._removeLoadItem = function (loader) {
    var l = this._currentLoads.length;
    for (var i = 0; i < l; i++) {
      if (this._currentLoads[i] == loader) {
        this._currentLoads.splice(i, 1);
        break;
      }
    }
  };

  /**
   * Remove unneeded references from a loader.
   *
   * @param loader
   * @private
   */
  p._cleanLoadItem = function(loader) {
    var item = loader.getItem();
    if (item) {
      delete item._loader;
    }
  }

  /**
   * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress.
   * @method _handleProgress
   * @param {ProgressEvent} event The progress event from the item.
   * @private
   */
  p._handleProgress = function (event) {
    var loader = event.target;
    this._sendFileProgress(loader.getItem(), loader.progress);
    this._updateProgress();
  };

  /**
   * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an
   * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before
   * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append
   * loaded progress on top of the already-loaded items.
   *
   * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be:
   * <ul>
   *      <li>5/10 of the items in the queue (50%)</li>
   *      <li>plus 20% of item 6's slot (2%)</li>
   *      <li>equals 52%</li>
   * </ul>
   * @method _updateProgress
   * @private
   */
  p._updateProgress = function () {
    var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress
    var remaining = this._numItems - this._numItemsLoaded;
    if (remaining > 0) {
      var chunk = 0;
      for (var i = 0, l = this._currentLoads.length; i < l; i++) {
        chunk += this._currentLoads[i].progress;
      }
      loaded += (chunk / remaining) * (remaining / this._numItems);
    }

    if (this._lastProgress != loaded) {
      this._sendProgress(loaded);
      this._lastProgress = loaded;
    }
  };

  /**
   * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal
   * hashes.
   * @method _disposeItem
   * @param {LoadItem|Object} item The item that was passed in for preloading.
   * @private
   */
  p._disposeItem = function (item) {
    delete this._loadedResults[item.id];
    delete this._loadedRawResults[item.id];
    delete this._loadItemsById[item.id];
    delete this._loadItemsBySrc[item.src];
  };

  /**
   * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}
   * event for details on the event payload.
   * @method _sendFileProgress
   * @param {LoadItem|Object} item The item that is being loaded.
   * @param {Number} progress The amount the item has been loaded (between 0 and 1).
   * @protected
   */
  p._sendFileProgress = function (item, progress) {
    if (this._isCanceled() || this._paused) {
      return;
    }
    if (!this.hasEventListener("fileprogress")) {
      return;
    }

    //LM: Rework ProgressEvent to support this?
    var event = new createjs.Event("fileprogress");
    event.progress = progress;
    event.loaded = progress;
    event.total = 1;
    event.item = item;

    this.dispatchEvent(event);
  };

  /**
   * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for
   * details on the event payload.
   * @method _sendFileComplete
   * @param {LoadItemObject} item The item that is being loaded.
   * @param {AbstractLoader} loader
   * @protected
   */
  p._sendFileComplete = function (item, loader) {
    if (this._isCanceled() || this._paused) {
      return;
    }

    var event = new createjs.Event("fileload");
    event.loader = loader;
    event.item = item;
    event.result = this._loadedResults[item.id];
    event.rawResult = this._loadedRawResults[item.id];

    // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this.
    if (item.completeHandler) {
      item.completeHandler(event);
    }

    this.hasEventListener("fileload") && this.dispatchEvent(event);
  };

  /**
   * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see
   * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload.
   * @method _sendFileStart
   * @param {LoadItem|Object} item The item that is being loaded.
   * @protected
   */
  p._sendFileStart = function (item) {
    var event = new createjs.Event("filestart");
    event.item = item;
    this.hasEventListener("filestart") && this.dispatchEvent(event);
  };

  p.toString = function () {
    return "[PreloadJS LoadQueue]";
  };

  createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader");
}());

//##############################################################################
// TextLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for Text files.
   * @class TextLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function TextLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.TEXT);
  };

  var p = createjs.extend(TextLoader, createjs.AbstractLoader);
  var s = TextLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}},
   * but is also the default loader if a file type can not be determined.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.TEXT;
  };

  createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader");

}());

//##############################################################################
// BinaryLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer.
   * @class BinaryLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function BinaryLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.BINARY);
    this.on("initialize", this._updateXHR, this);
  };

  var p = createjs.extend(BinaryLoader, createjs.AbstractLoader);
  var s = BinaryLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.BINARY;
  };

  // private methods
  /**
   * Before the item loads, set the response type to "arraybuffer"
   * @property _updateXHR
   * @param {Event} event
   * @private
   */
  p._updateXHR = function (event) {
    event.loader.setResponseType("arraybuffer");
  };

  createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader");

}());

//##############################################################################
// CSSLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for CSS files.
   * @class CSSLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractLoader
   * @constructor
   */
  function CSSLoader(loadItem, preferXHR) {
    this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.CSS);

    // public properties
    this.resultFormatter = this._formatResult;

    // protected properties
    this._tagSrcAttribute = "href";

    if (preferXHR) {
      this._tag = document.createElement("style");
    } else {
      this._tag = document.createElement("link");
    }

    this._tag.rel = "stylesheet";
    this._tag.type = "text/css";
  };

  var p = createjs.extend(CSSLoader, createjs.AbstractLoader);
  var s = CSSLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.CSS;
  };

  // protected methods
  /**
   * The result formatter for CSS files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {HTMLLinkElement|HTMLStyleElement}
   * @private
   */
  p._formatResult = function (loader) {
    if (this._preferXHR) {
      var tag = loader.getTag();

      if (tag.styleSheet) { // IE
        tag.styleSheet.cssText = loader.getResult(true);
      } else {
        var textNode = document.createTextNode(loader.getResult(true));
        tag.appendChild(textNode);
      }
    } else {
      tag = this._tag;
    }

    createjs.DomUtils.appendToHead(tag);

    return tag;
  };

  createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader");

}());

//##############################################################################
// ImageLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for image files.
   * @class ImageLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractLoader
   * @constructor
   */
  function ImageLoader (loadItem, preferXHR) {
    this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);

    // public properties
    this.resultFormatter = this._formatResult;

    // protected properties
    this._tagSrcAttribute = "src";

    // Check if the preload item is already a tag.
    if (createjs.RequestUtils.isImageTag(loadItem)) {
      this._tag = loadItem;
    } else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
      this._tag = loadItem.src;
    } else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
      this._tag = loadItem.tag;
    }

    if (this._tag != null) {
      this._preferXHR = false;
    } else {
      this._tag = document.createElement("img");
    }

    this.on("initialize", this._updateXHR, this);
  };

  var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
  var s = ImageLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.IMAGE;
  };

  // public methods
  p.load = function () {
    if (this._tag.src != "" && this._tag.complete) {
      this._sendComplete();
      return;
    }

    var crossOrigin = this._item.crossOrigin;
    if (crossOrigin == true) { crossOrigin = "Anonymous"; }
    if (crossOrigin != null && !createjs.RequestUtils.isLocal(this._item.src)) {
      this._tag.crossOrigin = crossOrigin;
    }

    this.AbstractLoader_load();
  };

  // protected methods
  /**
   * Before the item loads, set its mimeType and responseType.
   * @property _updateXHR
   * @param {Event} event
   * @private
   */
  p._updateXHR = function (event) {
    event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';

    // Only exists for XHR
    if (event.loader.setResponseType) {
      event.loader.setResponseType("blob");
    }
  };

  /**
   * The result formatter for Image files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {HTMLImageElement}
   * @private
   */
  p._formatResult = function (loader) {
    var _this = this;
    return function (done) {
      var tag = _this._tag;
      var URL = window.URL || window.webkitURL;

      if (!_this._preferXHR) {
        //document.body.removeChild(tag);
      } else if (URL) {
        var objURL = URL.createObjectURL(loader.getResult(true));
        tag.src = objURL;
        tag.onload = function () {
          URL.revokeObjectURL(_this.src);
        }
      } else {
        tag.src = loader.getItem().src;
      }

      if (tag.complete) {
        done(tag);
      } else {
        tag.onload = function () {
          done(this);
        }
      }
    };
  };

  createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");

}());

//##############################################################################
// JavaScriptLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for JavaScript files.
   * @class JavaScriptLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractLoader
   * @constructor
   */
  function JavaScriptLoader(loadItem, preferXHR) {
    this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.JAVASCRIPT);

    // public properties
    this.resultFormatter = this._formatResult;

    // protected properties
    this._tagSrcAttribute = "src";
    this.setTag(document.createElement("script"));
  };

  var p = createjs.extend(JavaScriptLoader, createjs.AbstractLoader);
  var s = JavaScriptLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.JAVASCRIPT;
  };

  // protected methods
  /**
   * The result formatter for JavaScript files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {HTMLLinkElement|HTMLStyleElement}
   * @private
   */
  p._formatResult = function (loader) {
    var tag = loader.getTag();
    if (this._preferXHR) {
      tag.text = loader.getResult(true);
    }
    return tag;
  };

  createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader");

}());

//##############################################################################
// JSONLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for JSON files. To load JSON cross-domain, use JSONP and the {{#crossLink "JSONPLoader"}}{{/crossLink}}
   * instead. To load JSON-formatted manifests, use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to
   * load EaselJS SpriteSheets, use {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
   * @class JSONLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function JSONLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.JSON);

    // public properties
    this.resultFormatter = this._formatResult;
  };

  var p = createjs.extend(JSONLoader, createjs.AbstractLoader);
  var s = JSONLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.JSON && !item._loadAsJSONP;
  };

  // protected methods
  /**
   * The result formatter for JSON files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {HTMLLinkElement|HTMLStyleElement}
   * @private
   */
  p._formatResult = function (loader) {
    var json = null;
    try {
      json = createjs.DataUtils.parseJSON(loader.getResult(true));
    } catch (e) {
      var event = new createjs.ErrorEvent("JSON_FORMAT", null, e);
      this._sendError(event);
      return e;
    }

    return json;
  };

  createjs.JSONLoader = createjs.promote(JSONLoader, "AbstractLoader");

}());

//##############################################################################
// JSONPLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for JSONP files, which are JSON-formatted text files, wrapped in a callback. To load regular JSON
   * without a callback use the {{#crossLink "JSONLoader"}}{{/crossLink}} instead. To load JSON-formatted manifests,
   * use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to load EaselJS SpriteSheets, use
   * {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}.
   *
   * Note that JSONP files loaded concurrently require a <em>unique</em> callback. To ensure JSONP files are loaded
   * in order, either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1),
   * or set {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback.
   * @class JSONPLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function JSONPLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, false, createjs.AbstractLoader.JSONP);
    this.setTag(document.createElement("script"));
    this.getTag().type = "text/javascript";
  };

  var p = createjs.extend(JSONPLoader, createjs.AbstractLoader);
  var s = JSONPLoader;


  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.JSONP || item._loadAsJSONP;
  };

  // public methods
  p.cancel = function () {
    this.AbstractLoader_cancel();
    this._dispose();
  };

  /**
   * Loads the JSONp file.  Because of the unique loading needs of jsonP
   * we don't use the AbstractLoader.load() method.
   *
   * @method load
   *
   */
  p.load = function () {
    if (this._item.callback == null) {
      throw new Error('callback is required for loading JSONP requests.');
    }

    // TODO: Look into creating our own iFrame to handle the load
    // In the first attempt, FF did not get the result
    //   result instanceof Object did not work either
    //   so we would need to clone the result.
    if (window[this._item.callback] != null) {
      throw new Error(
        "JSONP callback '" +
        this._item.callback +
        "' already exists on window. You need to specify a different callback or re-name the current one.");
    }

    window[this._item.callback] = createjs.proxy(this._handleLoad, this);
    window.document.body.appendChild(this._tag);

    this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout);

    // Load the tag
    this._tag.src = this._item.src;
  };

  // private methods
  /**
   * Handle the JSONP callback, which is a public method defined on `window`.
   * @method _handleLoad
   * @param {Object} data The formatted JSON data.
   * @private
   */
  p._handleLoad = function (data) {
    this._result = this._rawResult = data;
    this._sendComplete();

    this._dispose();
  };

  /**
   * The tag request has not loaded within the time specfied in loadTimeout.
   * @method _handleError
   * @param {Object} event The XHR error event.
   * @private
   */
  p._handleTimeout = function () {
    this._dispose();
    this.dispatchEvent(new createjs.ErrorEvent("timeout"));
  };

  /**
   * Clean up the JSONP load. This clears out the callback and script tag that this loader creates.
   * @method _dispose
   * @private
   */
  p._dispose = function () {
    window.document.body.removeChild(this._tag);
    delete window[this._item.callback];

    clearTimeout(this._loadTimeout);
  };

  createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader");

}());

//##############################################################################
// ManifestLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests
   * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the
   * {{#crossLink "LoadItem"}}{{/crossLink}}.
   *
   * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This
   * example shows a sample manifest definition, as well as how to to include a sub-manifest.
   *
   *    {
   *      "path": "assets/",
   *        "manifest": [
   *        "image.png",
   *        {"src": "image2.png", "id":"image2"},
   *        {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"}
   *        ]
   *    }
   *
   * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}},
   * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly.
   *
   * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are
   * higher priority loaders, so manifests <strong>must</strong> set the {{#crossLink "LoadItem"}}{{/crossLink}}
   * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}.
   * @class ManifestLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function ManifestLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.MANIFEST);

  // Public Properties
    /**
     * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}},
     * used to pass plugins to new LoadQueues that may be created.
     * @property _plugins
     * @type {Array}
     * @private
     * @since 0.6.1
     */
    this.plugins = null;


  // Protected Properties
    /**
     * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest.
     * @property _manifestQueue
     * @type {LoadQueue}
     * @private
     */
    this._manifestQueue = null;
  };

  var p = createjs.extend(ManifestLoader, createjs.AbstractLoader);
  var s = ManifestLoader;

  // static properties
  /**
   * The amount of progress that the manifest itself takes up.
   * @property MANIFEST_PROGRESS
   * @type {number}
   * @default 0.25 (25%)
   * @private
   * @static
   */
  s.MANIFEST_PROGRESS = 0.25;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.MANIFEST;
  };

  // public methods
  p.load = function () {
    this.AbstractLoader_load();
  };

  // protected methods
  p._createRequest = function() {
    var callback = this._item.callback;
    if (callback != null) {
      this._request = new createjs.JSONPLoader(this._item);
    } else {
      this._request = new createjs.JSONLoader(this._item);
    }
  };

  p.handleEvent = function (event) {
    switch (event.type) {
      case "complete":
        this._rawResult = event.target.getResult(true);
        this._result = event.target.getResult();
        this._sendProgress(s.MANIFEST_PROGRESS);
        this._loadManifest(this._result);
        return;
      case "progress":
        event.loaded *= s.MANIFEST_PROGRESS;
        this.progress = event.loaded / event.total;
        if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
        this._sendProgress(event);
        return;
    }
    this.AbstractLoader_handleEvent(event);
  };

  p.destroy = function() {
    this.AbstractLoader_destroy();
    this._manifestQueue.close();
  };

  /**
   * Create and load the manifest items once the actual manifest has been loaded.
   * @method _loadManifest
   * @param {Object} json
   * @private
   */
  p._loadManifest = function (json) {
    if (json && json.manifest) {
      var queue = this._manifestQueue = new createjs.LoadQueue();
      queue.on("fileload", this._handleManifestFileLoad, this);
      queue.on("progress", this._handleManifestProgress, this);
      queue.on("complete", this._handleManifestComplete, this, true);
      queue.on("error", this._handleManifestError, this, true);
      for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins
        queue.installPlugin(this.plugins[i]);
      }
      queue.loadManifest(json);
    } else {
      this._sendComplete();
    }
  };

  /**
   * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed.
   * @method _handleManifestFileLoad
   * @param {Event} event
   * @private
   */
  p._handleManifestFileLoad = function (event) {
    event.target = null;
    this.dispatchEvent(event);
  };

  /**
   * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
   * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader.
   * @method _handleManifestComplete
   * @param {Event} event
   * @private
   */
  p._handleManifestComplete = function (event) {
    this._loadedItems = this._manifestQueue.getItems(true);
    this._sendComplete();
  };

  /**
   * The manifest has reported progress.
   * @method _handleManifestProgress
   * @param {ProgressEvent} event
   * @private
   */
  p._handleManifestProgress = function (event) {
    this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS;
    this._sendProgress(this.progress);
  };

  /**
   * The manifest has reported an error with one of the files.
   * @method _handleManifestError
   * @param {ErrorEvent} event
   * @private
   */
  p._handleManifestError = function (event) {
    var newEvent = new createjs.Event("fileerror");
    newEvent.item = event.data;
    this.dispatchEvent(newEvent);
  };

  createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader");

}());

//##############################################################################
// SoundLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for HTML audio files. PreloadJS can not load WebAudio files, as a WebAudio context is required, which
   * should be created by either a library playing the sound (such as <a href="http://soundjs.com">SoundJS</a>, or an
   * external framework that handles audio playback. To load content that can be played by WebAudio, use the
   * {{#crossLink "BinaryLoader"}}{{/crossLink}}, and handle the audio context decoding manually.
   * @class SoundLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractMediaLoader
   * @constructor
   */
  function SoundLoader(loadItem, preferXHR) {
    this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SOUND);

    // protected properties
    if (createjs.RequestUtils.isAudioTag(loadItem)) {
      this._tag = loadItem;
    } else if (createjs.RequestUtils.isAudioTag(loadItem.src)) {
      this._tag = loadItem;
    } else if (createjs.RequestUtils.isAudioTag(loadItem.tag)) {
      this._tag = createjs.RequestUtils.isAudioTag(loadItem) ? loadItem : loadItem.src;
    }

    if (this._tag != null) {
      this._preferXHR = false;
    }
  };

  var p = createjs.extend(SoundLoader, createjs.AbstractMediaLoader);
  var s = SoundLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.SOUND;
  };

  // protected methods
  p._createTag = function (src) {
    var tag = document.createElement("audio");
    tag.autoplay = false;
    tag.preload = "none";

    //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works.
    tag.src = src;
    return tag;
  };

  createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader");

}());

//##############################################################################
// VideoLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for video files.
   * @class VideoLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractMediaLoader
   * @constructor
   */
  function VideoLoader(loadItem, preferXHR) {
    this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.VIDEO);

    if (createjs.RequestUtils.isVideoTag(loadItem) || createjs.RequestUtils.isVideoTag(loadItem.src)) {
      this.setTag(createjs.RequestUtils.isVideoTag(loadItem)?loadItem:loadItem.src);

      // We can't use XHR for a tag that's passed in.
      this._preferXHR = false;
    } else {
      this.setTag(this._createTag());
    }
  };

  var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader);
  var s = VideoLoader;

  /**
   * Create a new video tag
   *
   * @returns {HTMLElement}
   * @private
   */
  p._createTag = function () {
    return document.createElement("video");
  };

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.VIDEO;
  };

  createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader");

}());

//##############################################################################
// SpriteSheetLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader
   * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}}
   * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}}
   * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets <strong>must</strong>
   * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property
   * to {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}.
   * @class SpriteSheetLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function SpriteSheetLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.SPRITESHEET);

    // protected properties
    /**
     * An internal queue which loads the SpriteSheet's images.
     * @method _manifestQueue
     * @type {LoadQueue}
     * @private
     */
    this._manifestQueue = null;
  }

  var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader);
  var s = SpriteSheetLoader;

  // static properties
  /**
   * The amount of progress that the manifest itself takes up.
   * @property SPRITESHEET_PROGRESS
   * @type {number}
   * @default 0.25 (25%)
   * @private
   * @static
   */
  s.SPRITESHEET_PROGRESS = 0.25;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.SPRITESHEET;
  };

  // public methods
  p.destroy = function() {
    this.AbstractLoader_destroy;
    this._manifestQueue.close();
  };

  // protected methods
  p._createRequest = function() {
    var callback = this._item.callback;
    if (callback != null && callback instanceof Function) {
      this._request = new createjs.JSONPLoader(this._item);
    } else {
      this._request = new createjs.JSONLoader(this._item);
    }
  };

  p.handleEvent = function (event) {
    switch (event.type) {
      case "complete":
        this._rawResult = event.target.getResult(true);
        this._result = event.target.getResult();
        this._sendProgress(s.SPRITESHEET_PROGRESS);
        this._loadManifest(this._result);
        return;
      case "progress":
        event.loaded *= s.SPRITESHEET_PROGRESS;
        this.progress = event.loaded / event.total;
        if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
        this._sendProgress(event);
        return;
    }
    this.AbstractLoader_handleEvent(event);
  };

  /**
   * Create and load the images once the SpriteSheet JSON has been loaded.
   * @method _loadManifest
   * @param {Object} json
   * @private
   */
  p._loadManifest = function (json) {
    if (json && json.images) {
      var queue = this._manifestQueue = new createjs.LoadQueue();
      queue.on("complete", this._handleManifestComplete, this, true);
      queue.on("fileload", this._handleManifestFileLoad, this);
      queue.on("progress", this._handleManifestProgress, this);
      queue.on("error", this._handleManifestError, this, true);
      queue.loadManifest(json.images);
    }
  };

  /**
   * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed.
   * @method _handleManifestFileLoad
   * @param {Event} event
   * @private
   */
  p._handleManifestFileLoad = function (event) {
    var image = event.result;
    if (image != null) {
      var images = this.getResult().images;
      var pos = images.indexOf(event.item.src);
      images[pos] = image;
    }
  };

  /**
   * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
   * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader.
   * @method _handleManifestComplete
   * @param {Event} event
   * @private
   */
  p._handleManifestComplete = function (event) {
    this._result = new createjs.SpriteSheet(this._result);
    this._loadedItems = this._manifestQueue.getItems(true);
    this._sendComplete();
  };

  /**
   * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress.
   * @method _handleManifestProgress
   * @param {ProgressEvent} event
   * @private
   */
  p._handleManifestProgress = function (event) {
    this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS;
    this._sendProgress(this.progress);
  };

  /**
   * An image has reported an error.
   * @method _handleManifestError
   * @param {ErrorEvent} event
   * @private
   */
  p._handleManifestError = function (event) {
    var newEvent = new createjs.Event("fileerror");
    newEvent.item = event.data;
    this.dispatchEvent(newEvent);
  };

  createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader");

}());

//##############################################################################
// SVGLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for SVG files.
   * @class SVGLoader
   * @param {LoadItem|Object} loadItem
   * @param {Boolean} preferXHR
   * @extends AbstractLoader
   * @constructor
   */
  function SVGLoader(loadItem, preferXHR) {
    this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SVG);

    // public properties
    this.resultFormatter = this._formatResult;

    // protected properties
    this._tagSrcAttribute = "data";

    if (preferXHR) {
      this.setTag(document.createElement("svg"));
    } else {
      this.setTag(document.createElement("object"));
      this.getTag().type = "image/svg+xml";
    }
  };

  var p = createjs.extend(SVGLoader, createjs.AbstractLoader);
  var s = SVGLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.SVG;
  };

  // protected methods
  /**
   * The result formatter for SVG files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {Object}
   * @private
   */
  p._formatResult = function (loader) {
    // mime should be image/svg+xml, but Opera requires text/xml
    var xml = createjs.DataUtils.parseXML(loader.getResult(true), "text/xml");
    var tag = loader.getTag();

    if (!this._preferXHR && document.body.contains(tag)) {
      document.body.removeChild(tag);
    }

    if (xml.documentElement != null) {
      tag.appendChild(xml.documentElement);
      tag.style.visibility = "visible";
      return tag;
    } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8)
      return xml;
    }
  };

  createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader");

}());

//##############################################################################
// XMLLoader.js
//##############################################################################

(function () {
  "use strict";

  // constructor
  /**
   * A loader for CSS files.
   * @class XMLLoader
   * @param {LoadItem|Object} loadItem
   * @extends AbstractLoader
   * @constructor
   */
  function XMLLoader(loadItem) {
    this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.XML);

    // public properties
    this.resultFormatter = this._formatResult;
  };

  var p = createjs.extend(XMLLoader, createjs.AbstractLoader);
  var s = XMLLoader;

  // static methods
  /**
   * Determines if the loader can load a specific item. This loader can only load items that are of type
   * {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}.
   * @method canLoadItem
   * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
   * @returns {Boolean} Whether the loader can load the item.
   * @static
   */
  s.canLoadItem = function (item) {
    return item.type == createjs.AbstractLoader.XML;
  };

  // protected methods
  /**
   * The result formatter for XML files.
   * @method _formatResult
   * @param {AbstractLoader} loader
   * @returns {XMLDocument}
   * @private
   */
  p._formatResult = function (loader) {
    return createjs.DataUtils.parseXML(loader.getResult(true), "text/xml");
  };

  createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader");

}());

//##############################################################################
// version.js
//##############################################################################

(function () {

  /**
   * Static class holding library specific information such as the version and buildDate of the library.
   * The SoundJS class has been renamed {{#crossLink "Sound"}}{{/crossLink}}.  Please see {{#crossLink "Sound"}}{{/crossLink}}
   * for information on using sound.
   * @class SoundJS
   **/
  var s = createjs.SoundJS = createjs.SoundJS || {};

  /**
   * The version string for this release.
   * @property version
   * @type String
   * @static
   **/
  s.version = /*=version*/"0.6.1"; // injected by build process

  /**
   * The build date for this release in UTC format.
   * @property buildDate
   * @type String
   * @static
   **/
  s.buildDate = /*=date*/"Thu, 21 May 2015 16:17:37 GMT"; // injected by build process

})();

//##############################################################################
// IndexOf.js
//##############################################################################

/**
 * @class Utility Methods
 */

/**
 * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of
 * that value.  Returns -1 if value is not found.
 *
 *      var i = createjs.indexOf(myArray, myElementToFind);
 *
 * @method indexOf
 * @param {Array} array Array to search for searchElement
 * @param searchElement Element to find in array.
 * @return {Number} The first index of searchElement in array.
 */
createjs.indexOf = function (array, searchElement){
  "use strict";

  for (var i = 0,l=array.length; i < l; i++) {
    if (searchElement === array[i]) {
      return i;
    }
  }
  return -1;
};

//##############################################################################
// Proxy.js
//##############################################################################

/**
 * Various utilities that the CreateJS Suite uses. Utilities are created as separate files, and will be available on the
 * createjs namespace directly.
 *
 * <h4>Example</h4>
 *
 *      myObject.addEventListener("change", createjs.proxy(myMethod, scope));
 *
 * @class Utility Methods
 * @main Utility Methods
 */

(function() {
  "use strict";

  /**
   * A function proxy for methods. By default, JavaScript methods do not maintain scope, so passing a method as a
   * callback will result in the method getting called in the scope of the caller. Using a proxy ensures that the
   * method gets called in the correct scope.
   *
   * Additional arguments can be passed that will be applied to the function when it is called.
   *
   * <h4>Example</h4>
   *
   *      myObject.addEventListener("event", createjs.proxy(myHandler, this, arg1, arg2));
   *
   *      function myHandler(arg1, arg2) {
   *           // This gets called when myObject.myCallback is executed.
   *      }
   *
   * @method proxy
   * @param {Function} method The function to call
   * @param {Object} scope The scope to call the method name on
   * @param {mixed} [arg] * Arguments that are appended to the callback for additional params.
   * @public
   * @static
   */
  createjs.proxy = function (method, scope) {
    var aArgs = Array.prototype.slice.call(arguments, 2);
    return function () {
      return method.apply(scope, Array.prototype.slice.call(arguments, 0).concat(aArgs));
    };
  }

}());

//##############################################################################
// AudioSprite.js
//##############################################################################

//  NOTE this is "Class" is purely to document audioSprite Setup and usage.


/**
 * <strong>Note: AudioSprite is not a class, but its usage is easily lost in the documentation, so it has been called
 * out here for quick reference.</strong>
 *
 * Audio sprites are much like CSS sprites or image sprite sheets: multiple audio assets grouped into a single file.
 * Audio sprites work around limitations in certain browsers, where only a single sound can be loaded and played at a
 * time. We recommend at least 300ms of silence between audio clips to deal with HTML audio tag inaccuracy, and to prevent
 * accidentally playing bits of the neighbouring clips.
 *
 * <strong>Benefits of Audio Sprites:</strong>
 * <ul>
 *     <li>More robust support for older browsers and devices that only allow a single audio instance, such as iOS 5.</li>
 *     <li>They provide a work around for the Internet Explorer 9 audio tag limit, which restricts how many different
 *     sounds that could be loaded at once.</li>
 *     <li>Faster loading by only requiring a single network request for several sounds, especially on mobile devices
 * where the network round trip for each file can add significant latency.</li>
 * </ul>
 *
 * <strong>Drawbacks of Audio Sprites</strong>
 * <ul>
 *     <li>No guarantee of smooth looping when using HTML or Flash audio. If you have a track that needs to loop
 *    smoothly and you are supporting non-web audio browsers, do not use audio sprites for that sound if you can avoid
 *    it.</li>
 *     <li>No guarantee that HTML audio will play back immediately, especially the first time. In some browsers
 *     (Chrome!), HTML audio will only load enough to play through at the current download speed â€“ so we rely on the
 *     `canplaythrough` event to determine if the audio is loaded. Since audio sprites must jump ahead to play specific
 *     sounds, the audio may not yet have downloaded fully.</li>
 *     <li>Audio sprites share the same core source, so if you have a sprite with 5 sounds and are limited to 2
 *    concurrently playing instances, you can only play 2 of the sounds at the same time.</li>
 * </ul>
 *
 * <h4>Example</h4>
 *
 *    createjs.Sound.initializeDefaultPlugins();
 *    var assetsPath = "./assets/";
 *    var sounds = [{
 *      src:"MyAudioSprite.ogg", data: {
 *        audioSprite: [
 *          {id:"sound1", startTime:0, duration:500},
 *          {id:"sound2", startTime:1000, duration:400},
 *          {id:"sound3", startTime:1700, duration: 1000}
 *        ]}
 *      }
 *    ];
 *    createjs.Sound.alternateExtensions = ["mp3"];
 *    createjs.Sound.on("fileload", loadSound);
 *    createjs.Sound.registerSounds(sounds, assetsPath);
 *    // after load is complete
 *    createjs.Sound.play("sound2");
 *
 * You can also create audio sprites on the fly by setting the startTime and duration when creating an new AbstractSoundInstance.
 *
 *    createjs.Sound.play("MyAudioSprite", {startTime: 1000, duration: 400});
 *
 * The excellent CreateJS community has created a tool to create audio sprites, available at
 * <a href="https://github.com/tonistiigi/audiosprite" target="_blank">https://github.com/tonistiigi/audiosprite</a>,
 * as well as a <a href="http://jsfiddle.net/bharat_battu/g8fFP/12/" target="_blank">jsfiddle</a> to convert the output
 * to SoundJS format.
 *
 * @class AudioSprite
 * @since 0.6.0
 */

//##############################################################################
// PlayPropsConfig.js
//##############################################################################

(function () {
  "use strict";
  /**
   * A class to store the optional play properties passed in {{#crossLink "Sound/play"}}{{/crossLink}} and
   * {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}} calls.
   *
   * Optional Play Properties Include:
   * <ul>
   * <li>interrupt - How to interrupt any currently playing instances of audio with the same source,
   * if the maximum number of instances of the sound are already playing. Values are defined as <code>INTERRUPT_TYPE</code>
   * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}.</li>
   * <li>delay - The amount of time to delay the start of audio playback, in milliseconds.</li>
   * <li>offset - The offset from the start of the audio to begin playback, in milliseconds.</li>
   * <li>loop - How many times the audio loops when it reaches the end of playback. The default is 0 (no
   * loops), and -1 can be used for infinite playback.</li>
   * <li>volume - The volume of the sound, between 0 and 1. Note that the master volume is applied
   * against the individual volume.</li>
   * <li>pan - The left-right pan of the sound (if supported), between -1 (left) and 1 (right).</li>
   * <li>startTime - To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds.</li>
   * <li>duration - To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds.</li>
   * </ul>
   *
   * <h4>Example</h4>
   *
   *  var ppc = new createjs.PlayPropsConfig().set({interrupt: createjs.Sound.INTERRUPT_ANY, loop: -1, volume: 0.5})
   *  createjs.Sound.play("mySound", ppc);
   *  mySoundInstance.play(ppc);
   *
   * @class PlayPropsConfig
   * @constructor
   * @since 0.6.1
   */
  // TODO think of a better name for this class
  var PlayPropsConfig = function () {
// Public Properties
    /**
     * How to interrupt any currently playing instances of audio with the same source,
     * if the maximum number of instances of the sound are already playing. Values are defined as
     * <code>INTERRUPT_TYPE</code> constants on the Sound class, with the default defined by
     * {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}.
     * @property interrupt
     * @type {string}
     * @default null
     */
    this.interrupt = null;

    /**
     * The amount of time to delay the start of audio playback, in milliseconds.
     * @property delay
     * @type {Number}
     * @default null
     */
    this.delay = null;

    /**
     * The offset from the start of the audio to begin playback, in milliseconds.
     * @property offset
     * @type {number}
     * @default null
     */
    this.offset = null;

    /**
     * How many times the audio loops when it reaches the end of playback. The default is 0 (no
     * loops), and -1 can be used for infinite playback.
     * @property loop
     * @type {number}
     * @default null
     */
    this.loop = null;

    /**
     * The volume of the sound, between 0 and 1. Note that the master volume is applied
     * against the individual volume.
     * @property volume
     * @type {number}
     * @default null
     */
    this.volume = null;

    /**
     * The left-right pan of the sound (if supported), between -1 (left) and 1 (right).
     * @property pan
     * @type {number}
     * @default null
     */
    this.pan = null;

    /**
     * Used to create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds.
     * @property startTime
     * @type {number}
     * @default null
     */
    this.startTime = null;

    /**
     * Used to create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds.
     * @property duration
     * @type {number}
     * @default null
     */
    this.duration = null;
  };
  var p = PlayPropsConfig.prototype = {};
  var s = PlayPropsConfig;


// Static Methods
  /**
   * Creates a PlayPropsConfig from another PlayPropsConfig or an Object.
   *
   * @method create
   * @param {PlayPropsConfig|Object} value The play properties
   * @returns {PlayPropsConfig}
   * @static
   */
  s.create = function (value) {
    if (value instanceof s || value instanceof Object) {
      var ppc = new createjs.PlayPropsConfig();
      ppc.set(value);
      return ppc;
    } else {
      throw new Error("Type not recognized.");
    }
  };

// Public Methods
  /**
   * Provides a chainable shortcut method for setting a number of properties on the instance.
   *
   * <h4>Example</h4>
   *
   *      var PlayPropsConfig = new createjs.PlayPropsConfig().set({loop:-1, volume:0.7});
   *
   * @method set
   * @param {Object} props A generic object containing properties to copy to the PlayPropsConfig instance.
   * @return {PlayPropsConfig} Returns the instance the method is called on (useful for chaining calls.)
  */
  p.set = function(props) {
    for (var n in props) { this[n] = props[n]; }
    return this;
  };

  p.toString = function() {
    return "[PlayPropsConfig]";
  };

  createjs.PlayPropsConfig = s;

}());

//##############################################################################
// Sound.js
//##############################################################################

(function () {
  "use strict";

  /**
   * The Sound class is the public API for creating sounds, controlling the overall sound levels, and managing plugins.
   * All Sound APIs on this class are static.
   *
   * <b>Registering and Preloading</b><br />
   * Before you can play a sound, it <b>must</b> be registered. You can do this with {{#crossLink "Sound/registerSound"}}{{/crossLink}},
   * or register multiple sounds using {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. If you don't register a
   * sound prior to attempting to play it using {{#crossLink "Sound/play"}}{{/crossLink}} or create it using {{#crossLink "Sound/createInstance"}}{{/crossLink}},
   * the sound source will be automatically registered but playback will fail as the source will not be ready. If you use
   * <a href="http://preloadjs.com" target="_blank">PreloadJS</a>, registration is handled for you when the sound is
   * preloaded. It is recommended to preload sounds either internally using the register functions or externally using
   * PreloadJS so they are ready when you want to use them.
   *
   * <b>Playback</b><br />
   * To play a sound once it's been registered and preloaded, use the {{#crossLink "Sound/play"}}{{/crossLink}} method.
   * This method returns a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} which can be paused, resumed, muted, etc.
   * Please see the {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} documentation for more on the instance control APIs.
   *
   * <b>Plugins</b><br />
   * By default, the {{#crossLink "WebAudioPlugin"}}{{/crossLink}} or the {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}
   * are used (when available), although developers can change plugin priority or add new plugins (such as the
   * provided {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}). Please see the {{#crossLink "Sound"}}{{/crossLink}} API
   * methods for more on the playback and plugin APIs. To install plugins, or specify a different plugin order, see
   * {{#crossLink "Sound/installPlugins"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *      createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio";
   *      createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashAudioPlugin]);
   *      createjs.Sound.alternateExtensions = ["mp3"];
   *      createjs.Sound.on("fileload", createjs.proxy(this.loadHandler, (this)));
   *      createjs.Sound.registerSound("path/to/mySound.ogg", "sound");
   *      function loadHandler(event) {
     *          // This is fired for each sound that is registered.
     *          var instance = createjs.Sound.play("sound");  // play using id.  Could also use full source path or event.src.
     *          instance.on("complete", createjs.proxy(this.handleComplete, this));
     *          instance.volume = 0.5;
   *      }
   *
   * The maximum number of concurrently playing instances of the same sound can be specified in the "data" argument
   * of {{#crossLink "Sound/registerSound"}}{{/crossLink}}.  Note that if not specified, the active plugin will apply
   * a default limit.  Currently HTMLAudioPlugin sets a default limit of 2, while WebAudioPlugin and FlashAudioPlugin set a
   * default limit of 100.
   *
   *      createjs.Sound.registerSound("sound.mp3", "soundId", 4);
   *
   * Sound can be used as a plugin with PreloadJS to help preload audio properly. Audio preloaded with PreloadJS is
   * automatically registered with the Sound class. When audio is not preloaded, Sound will do an automatic internal
   * load. As a result, it may fail to play the first time play is called if the audio is not finished loading. Use the
   * {{#crossLink "Sound/fileload"}}{{/crossLink}} event to determine when a sound has finished internally preloading.
   * It is recommended that all audio is preloaded before it is played.
   *
   *      var queue = new createjs.LoadQueue();
   *    queue.installPlugin(createjs.Sound);
   *
   * <b>Audio Sprites</b><br />
   * SoundJS has added support for {{#crossLink "AudioSprite"}}{{/crossLink}}, available as of version 0.6.0.
   * For those unfamiliar with audio sprites, they are much like CSS sprites or sprite sheets: multiple audio assets
   * grouped into a single file.
   *
   * <h4>Example</h4>
   *
   *    var assetsPath = "./assets/";
   *    var sounds = [{
   *      src:"MyAudioSprite.ogg", data: {
   *        audioSprite: [
   *          {id:"sound1", startTime:0, duration:500},
   *          {id:"sound2", startTime:1000, duration:400},
   *          {id:"sound3", startTime:1700, duration: 1000}
   *        ]}
   *      }
   *    ];
   *    createjs.Sound.alternateExtensions = ["mp3"];
   *    createjs.Sound.on("fileload", loadSound);
   *    createjs.Sound.registerSounds(sounds, assetsPath);
   *    // after load is complete
   *    createjs.Sound.play("sound2");
   *
   * <b>Mobile Safe Approach</b><br />
   * Mobile devices require sounds to be played inside of a user initiated event (touch/click) in varying degrees.
   * As of SoundJS 0.4.1, you can launch a site inside of a user initiated event and have audio playback work. To
   * enable as broadly as possible, the site needs to setup the Sound plugin in its initialization (for example via
   * <code>createjs.Sound.initializeDefaultPlugins();</code>), and all sounds need to be played in the scope of the
   * application.  See the MobileSafe demo for a working example.
   *
   * <h4>Example</h4>
   *
   *     document.getElementById("status").addEventListener("click", handleTouch, false);    // works on Android and iPad
   *     function handleTouch(event) {
   *         document.getElementById("status").removeEventListener("click", handleTouch, false);    // remove the listener
   *         var thisApp = new myNameSpace.MyApp();    // launch the app
   *     }
   *
   * <b>Loading Alternate Paths and Extensionless Files</b><br />
   * SoundJS supports loading alternate paths and extensionless files by passing an object for src that has various paths
   * with property labels matching the extension.  These labels are how SoundJS determines if the browser will support the sound.
   * Priority is determined by the property order (first property is tried first).  This is supported by both internal loading
   * and loading with PreloadJS.
   *
   * Note an id is required for playback.
   *
   * <h4>Example</h4>
   *
   *    var sounds = {path:"./audioPath/",
   *        manifest: [
   *        {id: "cool", src: {mp3:"mp3/awesome.mp3", ogg:"noExtensionOggFile"}}
   *    ]};
   *
   *    createjs.Sound.alternateExtensions = ["mp3"];
   *    createjs.Sound.addEventListener("fileload", handleLoad);
   *    createjs.Sound.registerSounds(sounds);
   *
   * <h4>Known Browser and OS issues</h4>
   * <b>IE 9 HTML Audio limitations</b><br />
   * <ul><li>There is a delay in applying volume changes to tags that occurs once playback is started. So if you have
   * muted all sounds, they will all play during this delay until the mute applies internally. This happens regardless of
   * when or how you apply the volume change, as the tag seems to need to play to apply it.</li>
     * <li>MP3 encoding will not always work for audio tags, particularly in Internet Explorer. We've found default
   * encoding with 64kbps works.</li>
   * <li>Occasionally very short samples will get cut off.</li>
   * <li>There is a limit to how many audio tags you can load and play at once, which appears to be determined by
   * hardware and browser settings.  See {{#crossLink "HTMLAudioPlugin.MAX_INSTANCES"}}{{/crossLink}} for a safe estimate.</li></ul>
   *
   * <b>Firefox 25 Web Audio limitations</b>
   * <ul><li>mp3 audio files do not load properly on all windows machines, reported
   * <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=929969" target="_blank">here</a>. </br>
   * For this reason it is recommended to pass another FF supported type (ie ogg) first until this bug is resolved, if possible.</li></ul>

   * <b>Safari limitations</b><br />
   * <ul><li>Safari requires Quicktime to be installed for audio playback.</li></ul>
   *
   * <b>iOS 6 Web Audio limitations</b><br />
   * <ul><li>Sound is initially muted and will only unmute through play being called inside a user initiated event
   * (touch/click).</li>
   * <li>A bug exists that will distort un-cached web audio when a video element is present in the DOM that has audio at a different sampleRate.</li>
   * </ul>
   *
   * <b>Android HTML Audio limitations</b><br />
   * <ul><li>We have no control over audio volume. Only the user can set volume on their device.</li>
   * <li>We can only play audio inside a user event (touch/click).  This currently means you cannot loop sound or use
   * a delay.</li></ul>
   *
   * <b>Web Audio and PreloadJS</b><br />
   * <ul><li>Web Audio must be loaded through XHR, therefore when used with PreloadJS tag loading is not possible.  This means that tag loading cannot
   * be used to avoid cross domain issues if WebAudioPlugin is used</li><ul>
   *
   * @class Sound
   * @static
   * @uses EventDispatcher
   */
  function Sound() {
    throw "Sound cannot be instantiated";
  }

  var s = Sound;


// Static Properties
  /**
   * The interrupt value to interrupt any currently playing instance with the same source, if the maximum number of
   * instances of the sound are already playing.
   * @property INTERRUPT_ANY
   * @type {String}
   * @default any
   * @static
   */
  s.INTERRUPT_ANY = "any";

  /**
   * The interrupt value to interrupt the earliest currently playing instance with the same source that progressed the
   * least distance in the audio track, if the maximum number of instances of the sound are already playing.
   * @property INTERRUPT_EARLY
   * @type {String}
   * @default early
   * @static
   */
  s.INTERRUPT_EARLY = "early";

  /**
   * The interrupt value to interrupt the currently playing instance with the same source that progressed the most
   * distance in the audio track, if the maximum number of instances of the sound are already playing.
   * @property INTERRUPT_LATE
   * @type {String}
   * @default late
   * @static
   */
  s.INTERRUPT_LATE = "late";

  /**
   * The interrupt value to not interrupt any currently playing instances with the same source, if the maximum number of
   * instances of the sound are already playing.
   * @property INTERRUPT_NONE
   * @type {String}
   * @default none
   * @static
   */
  s.INTERRUPT_NONE = "none";

  /**
   * Defines the playState of an instance that is still initializing.
   * @property PLAY_INITED
   * @type {String}
   * @default playInited
   * @static
   */
  s.PLAY_INITED = "playInited";

  /**
   * Defines the playState of an instance that is currently playing or paused.
   * @property PLAY_SUCCEEDED
   * @type {String}
   * @default playSucceeded
   * @static
   */
  s.PLAY_SUCCEEDED = "playSucceeded";

  /**
   * Defines the playState of an instance that was interrupted by another instance.
   * @property PLAY_INTERRUPTED
   * @type {String}
   * @default playInterrupted
   * @static
   */
  s.PLAY_INTERRUPTED = "playInterrupted";

  /**
   * Defines the playState of an instance that completed playback.
   * @property PLAY_FINISHED
   * @type {String}
   * @default playFinished
   * @static
   */
  s.PLAY_FINISHED = "playFinished";

  /**
   * Defines the playState of an instance that failed to play. This is usually caused by a lack of available channels
   * when the interrupt mode was "INTERRUPT_NONE", the playback stalled, or the sound could not be found.
   * @property PLAY_FAILED
   * @type {String}
   * @default playFailed
   * @static
   */
  s.PLAY_FAILED = "playFailed";

  /**
   * A list of the default supported extensions that Sound will <i>try</i> to play. Plugins will check if the browser
   * can play these types, so modifying this list before a plugin is initialized will allow the plugins to try to
   * support additional media types.
   *
   * NOTE this does not currently work for {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}.
   *
   * More details on file formats can be found at <a href="http://en.wikipedia.org/wiki/Audio_file_format" target="_blank">http://en.wikipedia.org/wiki/Audio_file_format</a>.<br />
   * A very detailed list of file formats can be found at <a href="http://www.fileinfo.com/filetypes/audio" target="_blank">http://www.fileinfo.com/filetypes/audio</a>.
   * @property SUPPORTED_EXTENSIONS
   * @type {Array[String]}
   * @default ["mp3", "ogg", "opus", "mpeg", "wav", "m4a", "mp4", "aiff", "wma", "mid"]
   * @since 0.4.0
   * @static
   */
  s.SUPPORTED_EXTENSIONS = ["mp3", "ogg", "opus", "mpeg", "wav", "m4a", "mp4", "aiff", "wma", "mid"];

  /**
   * Some extensions use another type of extension support to play (one of them is a codex).  This allows you to map
   * that support so plugins can accurately determine if an extension is supported.  Adding to this list can help
   * plugins determine more accurately if an extension is supported.
   *
   * A useful list of extensions for each format can be found at <a href="http://html5doctor.com/html5-audio-the-state-of-play/" target="_blank">http://html5doctor.com/html5-audio-the-state-of-play/</a>.
   * @property EXTENSION_MAP
   * @type {Object}
   * @since 0.4.0
   * @default {m4a:"mp4"}
   * @static
   */
  s.EXTENSION_MAP = {
    m4a:"mp4"
  };

  /**
   * The RegExp pattern used to parse file URIs. This supports simple file names, as well as full domain URIs with
   * query strings. The resulting match is: protocol:$1 domain:$2 path:$3 file:$4 extension:$5 query:$6.
   * @property FILE_PATTERN
   * @type {RegExp}
   * @static
   * @protected
   */
  s.FILE_PATTERN = /^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/;


// Class Public properties
  /**
   * Determines the default behavior for interrupting other currently playing instances with the same source, if the
   * maximum number of instances of the sound are already playing.  Currently the default is {{#crossLink "Sound/INTERRUPT_NONE:property"}}{{/crossLink}}
   * but this can be set and will change playback behavior accordingly.  This is only used when {{#crossLink "Sound/play"}}{{/crossLink}}
   * is called without passing a value for interrupt.
   * @property defaultInterruptBehavior
   * @type {String}
   * @default Sound.INTERRUPT_NONE, or "none"
   * @static
   * @since 0.4.0
   */
  s.defaultInterruptBehavior = s.INTERRUPT_NONE;  // OJR does s.INTERRUPT_ANY make more sense as default?  Needs game dev testing to see which case makes more sense.

  /**
   * An array of extensions to attempt to use when loading sound, if the default is unsupported by the active plugin.
   * These are applied in order, so if you try to Load Thunder.ogg in a browser that does not support ogg, and your
   * extensions array is ["mp3", "m4a", "wav"] it will check mp3 support, then m4a, then wav. The audio files need
   * to exist in the same location, as only the extension is altered.
   *
   * Note that regardless of which file is loaded, you can call {{#crossLink "Sound/createInstance"}}{{/crossLink}}
   * and {{#crossLink "Sound/play"}}{{/crossLink}} using the same id or full source path passed for loading.
   *
   * <h4>Example</h4>
   *
   *  var sounds = [
   *    {src:"myPath/mySound.ogg", id:"example"},
   *  ];
   *  createjs.Sound.alternateExtensions = ["mp3"]; // now if ogg is not supported, SoundJS will try asset0.mp3
   *  createjs.Sound.on("fileload", handleLoad); // call handleLoad when each sound loads
   *  createjs.Sound.registerSounds(sounds, assetPath);
   *  // ...
   *  createjs.Sound.play("myPath/mySound.ogg"); // works regardless of what extension is supported.  Note calling with ID is a better approach
   *
   * @property alternateExtensions
   * @type {Array}
   * @since 0.5.2
   * @static
   */
  s.alternateExtensions = [];

  /**
   * The currently active plugin. If this is null, then no plugin could be initialized. If no plugin was specified,
   * Sound attempts to apply the default plugins: {{#crossLink "WebAudioPlugin"}}{{/crossLink}}, followed by
   * {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}.
   * @property activePlugin
   * @type {Object}
   * @static
   */
    s.activePlugin = null;


// class getter / setter properties
  /**
   * Set the master volume of Sound. The master volume is multiplied against each sound's individual volume.  For
   * example, if master volume is 0.5 and a sound's volume is 0.5, the resulting volume is 0.25. To set individual
   * sound volume, use AbstractSoundInstance {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} instead.
   *
   * <h4>Example</h4>
   *
   *     createjs.Sound.volume = 0.5;
   *
   *
   * @property volume
   * @type {Number}
   * @default 1
   * @since 0.6.1
   */
  s._masterVolume = 1;
  Object.defineProperty(s, "volume", {
    get: function () {return this._masterVolume;},
    set: function (value) {
        if (Number(value) == null) {return false;}
        value = Math.max(0, Math.min(1, value));
        s._masterVolume = value;
        if (!this.activePlugin || !this.activePlugin.setVolume || !this.activePlugin.setVolume(value)) {
          var instances = this._instances;
          for (var i = 0, l = instances.length; i < l; i++) {
            instances[i].setMasterVolume(value);
          }
        }
      }
  });

  /**
   * Mute/Unmute all audio. Note that muted audio still plays at 0 volume. This global mute value is maintained
   * separately and when set will override, but not change the mute property of individual instances. To mute an individual
   * instance, use AbstractSoundInstance {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} instead.
   *
   * <h4>Example</h4>
   *
   *     createjs.Sound.muted = true;
   *
   *
   * @property muted
   * @type {Boolean}
   * @default false
   * @since 0.6.1
   */
  s._masterMute = false;
  // OJR references to the methods were not working, so the code had to be duplicated here
  Object.defineProperty(s, "muted", {
    get: function () {return this._masterMute;},
    set: function (value) {
        if (value == null) {return false;}

        this._masterMute = value;
        if (!this.activePlugin || !this.activePlugin.setMute || !this.activePlugin.setMute(value)) {
          var instances = this._instances;
          for (var i = 0, l = instances.length; i < l; i++) {
            instances[i].setMasterMute(value);
          }
        }
        return true;
      }
  });

  /**
   * Get the active plugins capabilities, which help determine if a plugin can be used in the current environment,
   * or if the plugin supports a specific feature. Capabilities include:
   * <ul>
   *     <li><b>panning:</b> If the plugin can pan audio from left to right</li>
   *     <li><b>volume;</b> If the plugin can control audio volume.</li>
   *     <li><b>tracks:</b> The maximum number of audio tracks that can be played back at a time. This will be -1
   *     if there is no known limit.</li>
   * <br />An entry for each file type in {{#crossLink "Sound/SUPPORTED_EXTENSIONS:property"}}{{/crossLink}}:
   *     <li><b>mp3:</b> If MP3 audio is supported.</li>
   *     <li><b>ogg:</b> If OGG audio is supported.</li>
   *     <li><b>wav:</b> If WAV audio is supported.</li>
   *     <li><b>mpeg:</b> If MPEG audio is supported.</li>
   *     <li><b>m4a:</b> If M4A audio is supported.</li>
   *     <li><b>mp4:</b> If MP4 audio is supported.</li>
   *     <li><b>aiff:</b> If aiff audio is supported.</li>
   *     <li><b>wma:</b> If wma audio is supported.</li>
   *     <li><b>mid:</b> If mid audio is supported.</li>
   * </ul>
   *
   * You can get a specific capability of the active plugin using standard object notation
   *
   * <h4>Example</h4>
   *
   *      var mp3 = createjs.Sound.capabilities.mp3;
   *
   * Note this property is read only.
   *
   * @property capabilities
   * @type {Object}
   * @static
   * @readOnly
   * @since 0.6.1
   */
  Object.defineProperty(s, "capabilities", {
    get: function () {
          if (s.activePlugin == null) {return null;}
          return s.activePlugin._capabilities;
        },
    set: function (value) { return false;}
  });


// Class Private properties
  /**
   * Determines if the plugins have been registered. If false, the first call to play() will instantiate the default
   * plugins ({{#crossLink "WebAudioPlugin"}}{{/crossLink}}, followed by {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}).
   * If plugins have been registered, but none are applicable, then sound playback will fail.
   * @property _pluginsRegistered
   * @type {Boolean}
   * @default false
   * @static
   * @protected
   */
  s._pluginsRegistered = false;

  /**
   * Used internally to assign unique IDs to each AbstractSoundInstance.
   * @property _lastID
   * @type {Number}
   * @static
   * @protected
   */
  s._lastID = 0;

  /**
   * An array containing all currently playing instances. This allows Sound to control the volume, mute, and playback of
   * all instances when using static APIs like {{#crossLink "Sound/stop"}}{{/crossLink}} and {{#crossLink "Sound/setVolume"}}{{/crossLink}}.
   * When an instance has finished playback, it gets removed via the {{#crossLink "Sound/finishedPlaying"}}{{/crossLink}}
   * method. If the user replays an instance, it gets added back in via the {{#crossLink "Sound/_beginPlaying"}}{{/crossLink}}
   * method.
   * @property _instances
   * @type {Array}
   * @protected
   * @static
   */
  s._instances = [];

  /**
   * An object hash storing objects with sound sources, startTime, and duration via there corresponding ID.
   * @property _idHash
   * @type {Object}
   * @protected
   * @static
   */
  s._idHash = {};

  /**
   * An object hash that stores preloading sound sources via the parsed source that is passed to the plugin.  Contains the
   * source, id, and data that was passed in by the user.  Parsed sources can contain multiple instances of source, id,
   * and data.
   * @property _preloadHash
   * @type {Object}
   * @protected
   * @static
   */
  s._preloadHash = {};

  /**
   * An object hash storing {{#crossLink "PlayPropsConfig"}}{{/crossLink}} via the parsed source that is passed as defaultPlayProps in
   * {{#crossLink "Sound/registerSound"}}{{/crossLink}} and {{#crossLink "Sound/registerSounds"}}{{/crossLink}}.
   * @property _defaultPlayPropsHash
   * @type {Object}
   * @protected
   * @static
   * @since 0.6.1
   */
  s._defaultPlayPropsHash = {};


// EventDispatcher methods:
  s.addEventListener = null;
  s.removeEventListener = null;
  s.removeAllEventListeners = null;
  s.dispatchEvent = null;
  s.hasEventListener = null;
  s._listeners = null;

  createjs.EventDispatcher.initialize(s); // inject EventDispatcher methods.


// Events
  /**
   * This event is fired when a file finishes loading internally. This event is fired for each loaded sound,
   * so any handler methods should look up the <code>event.src</code> to handle a particular sound.
   * @event fileload
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {String} src The source of the sound that was loaded.
   * @param {String} [id] The id passed in when the sound was registered. If one was not provided, it will be null.
   * @param {Number|Object} [data] Any additional data associated with the item. If not provided, it will be undefined.
   * @since 0.4.1
   */

  /**
   * This event is fired when a file fails loading internally. This event is fired for each loaded sound,
   * so any handler methods should look up the <code>event.src</code> to handle a particular sound.
   * @event fileerror
   * @param {Object} target The object that dispatched the event.
   * @param {String} type The event type.
   * @param {String} src The source of the sound that was loaded.
   * @param {String} [id] The id passed in when the sound was registered. If one was not provided, it will be null.
   * @param {Number|Object} [data] Any additional data associated with the item. If not provided, it will be undefined.
   * @since 0.6.0
   */


// Class Public Methods
  /**
   * Get the preload rules to allow Sound to be used as a plugin by <a href="http://preloadjs.com" target="_blank">PreloadJS</a>.
   * Any load calls that have the matching type or extension will fire the callback method, and use the resulting
   * object, which is potentially modified by Sound. This helps when determining the correct path, as well as
   * registering the audio instance(s) with Sound. This method should not be called, except by PreloadJS.
   * @method getPreloadHandlers
   * @return {Object} An object containing:
   * <ul><li>callback: A preload callback that is fired when a file is added to PreloadJS, which provides
   *      Sound a mechanism to modify the load parameters, select the correct file format, register the sound, etc.</li>
   *      <li>types: A list of file types that are supported by Sound (currently supports "sound").</li>
   *      <li>extensions: A list of file extensions that are supported by Sound (see {{#crossLink "Sound/SUPPORTED_EXTENSIONS:property"}}{{/crossLink}}).</li></ul>
   * @static
   * @protected
   */
  s.getPreloadHandlers = function () {
    return {
      callback:createjs.proxy(s.initLoad, s),
      types:["sound"],
      extensions:s.SUPPORTED_EXTENSIONS
    };
  };

  /**
   * Used to dispatch fileload events from internal loading.
   * @method _handleLoadComplete
   * @param event A loader event.
   * @protected
   * @static
   * @since 0.6.0
   */
  s._handleLoadComplete = function(event) {
    var src = event.target.getItem().src;
    if (!s._preloadHash[src]) {return;}

    for (var i = 0, l = s._preloadHash[src].length; i < l; i++) {
      var item = s._preloadHash[src][i];
      s._preloadHash[src][i] = true;

      if (!s.hasEventListener("fileload")) { continue; }

      var event = new createjs.Event("fileload");
      event.src = item.src;
      event.id = item.id;
      event.data = item.data;
      event.sprite = item.sprite;

      s.dispatchEvent(event);
    }
  };

  /**
   * Used to dispatch error events from internal preloading.
   * @param event
   * @protected
   * @since 0.6.0
   * @static
   */
  s._handleLoadError = function(event) {
    var src = event.target.getItem().src;
    if (!s._preloadHash[src]) {return;}

    for (var i = 0, l = s._preloadHash[src].length; i < l; i++) {
      var item = s._preloadHash[src][i];
      s._preloadHash[src][i] = false;

      if (!s.hasEventListener("fileerror")) { continue; }

      var event = new createjs.Event("fileerror");
      event.src = item.src;
      event.id = item.id;
      event.data = item.data;
      event.sprite = item.sprite;

      s.dispatchEvent(event);
    }
  };

  /**
   * Used by {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} to register a Sound plugin.
   *
   * @method _registerPlugin
   * @param {Object} plugin The plugin class to install.
   * @return {Boolean} Whether the plugin was successfully initialized.
   * @static
   * @private
   */
  s._registerPlugin = function (plugin) {
    // Note: Each plugin is passed in as a class reference, but we store the activePlugin as an instance
    if (plugin.isSupported()) {
      s.activePlugin = new plugin();
      return true;
    }
    return false;
  };

  /**
   * Register a list of Sound plugins, in order of precedence. To register a single plugin, pass a single element in the array.
   *
   * <h4>Example</h4>
   *
   *      createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio/";
   *      createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin, createjs.FlashAudioPlugin]);
   *
   * @method registerPlugins
   * @param {Array} plugins An array of plugins classes to install.
   * @return {Boolean} Whether a plugin was successfully initialized.
   * @static
   */
  s.registerPlugins = function (plugins) {
    s._pluginsRegistered = true;
    for (var i = 0, l = plugins.length; i < l; i++) {
      if (s._registerPlugin(plugins[i])) {
        return true;
      }
    }
    return false;
  };

  /**
   * Initialize the default plugins. This method is automatically called when any audio is played or registered before
   * the user has manually registered plugins, and enables Sound to work without manual plugin setup. Currently, the
   * default plugins are {{#crossLink "WebAudioPlugin"}}{{/crossLink}} followed by {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *  if (!createjs.initializeDefaultPlugins()) { return; }
   *
   * @method initializeDefaultPlugins
   * @returns {Boolean} True if a plugin was initialized, false otherwise.
   * @since 0.4.0
   * @static
   */
  s.initializeDefaultPlugins = function () {
    if (s.activePlugin != null) {return true;}
    if (s._pluginsRegistered) {return false;}
    if (s.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin])) {return true;}
    return false;
  };

  /**
   * Determines if Sound has been initialized, and a plugin has been activated.
   *
   * <h4>Example</h4>
   * This example sets up a Flash fallback, but only if there is no plugin specified yet.
   *
   *  if (!createjs.Sound.isReady()) {
   *    createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio/";
   *    createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin, createjs.FlashAudioPlugin]);
   *  }
   *
   * @method isReady
   * @return {Boolean} If Sound has initialized a plugin.
   * @static
   */
  s.isReady = function () {
    return (s.activePlugin != null);
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/capabilities:property"}}{{/crossLink}} instead.
   *
   * @method getCapabilities
   * @return {Object} An object containing the capabilities of the active plugin.
   * @static
   * @deprecated
   */
  s.getCapabilities = function () {
    if (s.activePlugin == null) {return null;}
    return s.activePlugin._capabilities;
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/capabilities:property"}}{{/crossLink}} instead.
   *
   * @method getCapability
   * @param {String} key The capability to retrieve
   * @return {Number|Boolean} The value of the capability.
   * @static
   * @see getCapabilities
   * @deprecated
   */
  s.getCapability = function (key) {
    if (s.activePlugin == null) {return null;}
    return s.activePlugin._capabilities[key];
  };

  /**
   * Process manifest items from <a href="http://preloadjs.com" target="_blank">PreloadJS</a>. This method is intended
   * for usage by a plugin, and not for direct interaction.
   * @method initLoad
   * @param {Object} src The object to load.
   * @return {Object|AbstractLoader} An instance of AbstractLoader.
   * @protected
   * @static
   */
  s.initLoad = function (loadItem) {
    return s._registerSound(loadItem);
  };

  /**
   * Internal method for loading sounds.  This should not be called directly.
   *
   * @method _registerSound
   * @param {Object} src The object to load, containing src property and optionally containing id and data.
   * @return {Object} An object with the modified values that were passed in, which defines the sound.
   * Returns false if the source cannot be parsed or no plugins can be initialized.
   * Returns true if the source is already loaded.
   * @static
   * @private
   * @since 0.6.0
   */

  s._registerSound = function (loadItem) {
    if (!s.initializeDefaultPlugins()) {return false;}

    var details;
    if (loadItem.src instanceof Object) {
      details = s._parseSrc(loadItem.src);
      details.src = loadItem.path + details.src;
    } else {
      details = s._parsePath(loadItem.src);
    }
    if (details == null) {return false;}
    loadItem.src = details.src;
    loadItem.type = "sound";

    var data = loadItem.data;
    var numChannels = null;
    if (data != null) {
      if (!isNaN(data.channels)) {
        numChannels = parseInt(data.channels);
      } else if (!isNaN(data)) {
        numChannels = parseInt(data);
      }

      if(data.audioSprite) {
        var sp;
        for(var i = data.audioSprite.length; i--; ) {
          sp = data.audioSprite[i];
          s._idHash[sp.id] = {src: loadItem.src, startTime: parseInt(sp.startTime), duration: parseInt(sp.duration)};

          if (sp.defaultPlayProps) {
            s._defaultPlayPropsHash[sp.id] = createjs.PlayPropsConfig.create(sp.defaultPlayProps);
          }
        }
      }
    }
    if (loadItem.id != null) {s._idHash[loadItem.id] = {src: loadItem.src}};
    var loader = s.activePlugin.register(loadItem);

    SoundChannel.create(loadItem.src, numChannels);

    // return the number of instances to the user.  This will also be returned in the load event.
    if (data == null || !isNaN(data)) {
      loadItem.data = numChannels || SoundChannel.maxPerChannel();
    } else {
      loadItem.data.channels = numChannels || SoundChannel.maxPerChannel();
    }

    if (loader.type) {loadItem.type = loader.type;}

    if (loadItem.defaultPlayProps) {
      s._defaultPlayPropsHash[loadItem.src] = createjs.PlayPropsConfig.create(loadItem.defaultPlayProps);
    }
    return loader;
  };

  /**
   * Register an audio file for loading and future playback in Sound. This is automatically called when using
   * <a href="http://preloadjs.com" target="_blank">PreloadJS</a>.  It is recommended to register all sounds that
   * need to be played back in order to properly prepare and preload them. Sound does internal preloading when required.
   *
   * <h4>Example</h4>
   *
   *      createjs.Sound.alternateExtensions = ["mp3"];
   *      createjs.Sound.on("fileload", handleLoad); // add an event listener for when load is completed
   *      createjs.Sound.registerSound("myAudioPath/mySound.ogg", "myID", 3);
   *      createjs.Sound.registerSound({ogg:"path1/mySound.ogg", mp3:"path2/mySoundNoExtension"}, "myID", 3);
   *
   *
   * @method registerSound
   * @param {String | Object} src The source or an Object with a "src" property or an Object with multiple extension labeled src properties.
   * @param {String} [id] An id specified by the user to play the sound later.  Note id is required for when src is multiple extension labeled src properties.
   * @param {Number | Object} [data] Data associated with the item. Sound uses the data parameter as the number of
   * channels for an audio instance, however a "channels" property can be appended to the data object if it is used
   * for other information. The audio channels will set a default based on plugin if no value is found.
   * Sound also uses the data property to hold an {{#crossLink "AudioSprite"}}{{/crossLink}} array of objects in the following format {id, startTime, duration}.<br/>
   *   id used to play the sound later, in the same manner as a sound src with an id.<br/>
   *   startTime is the initial offset to start playback and loop from, in milliseconds.<br/>
   *   duration is the amount of time to play the clip for, in milliseconds.<br/>
   * This allows Sound to support audio sprites that are played back by id.
   * @param {string} basePath Set a path that will be prepended to src for loading.
   * @param {Object | PlayPropsConfig} defaultPlayProps Optional Playback properties that will be set as the defaults on any new AbstractSoundInstance.
   * See {{#crossLink "PlayPropsConfig"}}{{/crossLink}} for options.
   * @return {Object} An object with the modified values that were passed in, which defines the sound.
   * Returns false if the source cannot be parsed or no plugins can be initialized.
   * Returns true if the source is already loaded.
   * @static
   * @since 0.4.0
   */
  s.registerSound = function (src, id, data, basePath, defaultPlayProps) {
    var loadItem = {src: src, id: id, data:data, defaultPlayProps:defaultPlayProps};
    if (src instanceof Object && src.src) {
      basePath = id;
      loadItem = src;
    }
    loadItem = createjs.LoadItem.create(loadItem);
    loadItem.path = basePath;

    if (basePath != null && !(loadItem.src instanceof Object)) {loadItem.src = basePath + src;}

    var loader = s._registerSound(loadItem);
    if(!loader) {return false;}

    if (!s._preloadHash[loadItem.src]) { s._preloadHash[loadItem.src] = [];}
    s._preloadHash[loadItem.src].push(loadItem);
    if (s._preloadHash[loadItem.src].length == 1) {
      // OJR note this will disallow reloading a sound if loading fails or the source changes
      loader.on("complete", createjs.proxy(this._handleLoadComplete, this));
      loader.on("error", createjs.proxy(this._handleLoadError, this));
      s.activePlugin.preload(loader);
    } else {
      if (s._preloadHash[loadItem.src][0] == true) {return true;}
    }

    return loadItem;
  };

  /**
   * Register an array of audio files for loading and future playback in Sound. It is recommended to register all
   * sounds that need to be played back in order to properly prepare and preload them. Sound does internal preloading
   * when required.
   *
   * <h4>Example</h4>
   *
   *    var assetPath = "./myAudioPath/";
   *      var sounds = [
   *          {src:"asset0.ogg", id:"example"},
   *          {src:"asset1.ogg", id:"1", data:6},
   *          {src:"asset2.mp3", id:"works"}
   *          {src:{mp3:"path1/asset3.mp3", ogg:"path2/asset3NoExtension}, id:"better"}
   *      ];
   *      createjs.Sound.alternateExtensions = ["mp3"]; // if the passed extension is not supported, try this extension
   *      createjs.Sound.on("fileload", handleLoad); // call handleLoad when each sound loads
   *      createjs.Sound.registerSounds(sounds, assetPath);
   *
   * @method registerSounds
   * @param {Array} sounds An array of objects to load. Objects are expected to be in the format needed for
   * {{#crossLink "Sound/registerSound"}}{{/crossLink}}: <code>{src:srcURI, id:ID, data:Data}</code>
   * with "id" and "data" being optional.
   * You can also pass an object with path and manifest properties, where path is a basePath and manifest is an array of objects to load.
   * Note id is required if src is an object with extension labeled src properties.
   * @param {string} basePath Set a path that will be prepended to each src when loading.  When creating, playing, or removing
   * audio that was loaded with a basePath by src, the basePath must be included.
   * @return {Object} An array of objects with the modified values that were passed in, which defines each sound.
   * Like registerSound, it will return false for any values when the source cannot be parsed or if no plugins can be initialized.
   * Also, it will return true for any values when the source is already loaded.
   * @static
   * @since 0.6.0
   */
  s.registerSounds = function (sounds, basePath) {
    var returnValues = [];
    if (sounds.path) {
      if (!basePath) {
        basePath = sounds.path;
      } else {
        basePath = basePath + sounds.path;
      }
      sounds = sounds.manifest;
      // TODO document this feature
    }
    for (var i = 0, l = sounds.length; i < l; i++) {
      returnValues[i] = createjs.Sound.registerSound(sounds[i].src, sounds[i].id, sounds[i].data, basePath, sounds[i].defaultPlayProps);
    }
    return returnValues;
  };

  /**
   * Remove a sound that has been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or
   * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}.
   * <br />Note this will stop playback on active instances playing this sound before deleting them.
   * <br />Note if you passed in a basePath, you need to pass it or prepend it to the src here.
   *
   * <h4>Example</h4>
   *
   *      createjs.Sound.removeSound("myID");
   *      createjs.Sound.removeSound("myAudioBasePath/mySound.ogg");
   *      createjs.Sound.removeSound("myPath/myOtherSound.mp3", "myBasePath/");
   *      createjs.Sound.removeSound({mp3:"musicNoExtension", ogg:"music.ogg"}, "myBasePath/");
   *
   * @method removeSound
   * @param {String | Object} src The src or ID of the audio, or an Object with a "src" property, or an Object with multiple extension labeled src properties.
   * @param {string} basePath Set a path that will be prepended to each src when removing.
   * @return {Boolean} True if sound is successfully removed.
   * @static
   * @since 0.4.1
   */
  s.removeSound = function(src, basePath) {
    if (s.activePlugin == null) {return false;}

    if (src instanceof Object && src.src) {src = src.src;}

    var details;
    if (src instanceof Object) {
      details = s._parseSrc(src);
    } else {
      src = s._getSrcById(src).src;
      details = s._parsePath(src);
    }
    if (details == null) {return false;}
    src = details.src;
    if (basePath != null) {src = basePath + src;}

    for(var prop in s._idHash){
      if(s._idHash[prop].src == src) {
        delete(s._idHash[prop]);
      }
    }

    // clear from SoundChannel, which also stops and deletes all instances
    SoundChannel.removeSrc(src);

    delete(s._preloadHash[src]);

    s.activePlugin.removeSound(src);

    return true;
  };

  /**
   * Remove an array of audio files that have been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or
   * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}.
   * <br />Note this will stop playback on active instances playing this audio before deleting them.
   * <br />Note if you passed in a basePath, you need to pass it or prepend it to the src here.
   *
   * <h4>Example</h4>
   *
   *    assetPath = "./myPath/";
   *      var sounds = [
   *          {src:"asset0.ogg", id:"example"},
   *          {src:"asset1.ogg", id:"1", data:6},
   *          {src:"asset2.mp3", id:"works"}
   *      ];
   *      createjs.Sound.removeSounds(sounds, assetPath);
   *
   * @method removeSounds
   * @param {Array} sounds An array of objects to remove. Objects are expected to be in the format needed for
   * {{#crossLink "Sound/removeSound"}}{{/crossLink}}: <code>{srcOrID:srcURIorID}</code>.
   * You can also pass an object with path and manifest properties, where path is a basePath and manifest is an array of objects to remove.
   * @param {string} basePath Set a path that will be prepended to each src when removing.
   * @return {Object} An array of Boolean values representing if the sounds with the same array index were
   * successfully removed.
   * @static
   * @since 0.4.1
   */
  s.removeSounds = function (sounds, basePath) {
    var returnValues = [];
    if (sounds.path) {
      if (!basePath) {
        basePath = sounds.path;
      } else {
        basePath = basePath + sounds.path;
      }
      sounds = sounds.manifest;
    }
    for (var i = 0, l = sounds.length; i < l; i++) {
      returnValues[i] = createjs.Sound.removeSound(sounds[i].src, basePath);
    }
    return returnValues;
  };

  /**
   * Remove all sounds that have been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or
   * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}.
   * <br />Note this will stop playback on all active sound instances before deleting them.
   *
   * <h4>Example</h4>
   *
   *     createjs.Sound.removeAllSounds();
   *
   * @method removeAllSounds
   * @static
   * @since 0.4.1
   */
  s.removeAllSounds = function() {
    s._idHash = {};
    s._preloadHash = {};
    SoundChannel.removeAll();
    if (s.activePlugin) {s.activePlugin.removeAllSounds();}
  };

  /**
   * Check if a source has been loaded by internal preloaders. This is necessary to ensure that sounds that are
   * not completed preloading will not kick off a new internal preload if they are played.
   *
   * <h4>Example</h4>
   *
   *     var mySound = "assetPath/asset0.ogg";
   *     if(createjs.Sound.loadComplete(mySound) {
   *         createjs.Sound.play(mySound);
   *     }
   *
   * @method loadComplete
   * @param {String} src The src or id that is being loaded.
   * @return {Boolean} If the src is already loaded.
   * @since 0.4.0
   * @static
   */
  s.loadComplete = function (src) {
    if (!s.isReady()) { return false; }
    var details = s._parsePath(src);
    if (details) {
      src = s._getSrcById(details.src).src;
    } else {
      src = s._getSrcById(src).src;
    }
    if(s._preloadHash[src] == undefined) {return false;}
    return (s._preloadHash[src][0] == true);  // src only loads once, so if it's true for the first it's true for all
  };

  /**
   * Parse the path of a sound. Alternate extensions will be attempted in order if the
   * current extension is not supported
   * @method _parsePath
   * @param {String} value The path to an audio source.
   * @return {Object} A formatted object that can be registered with the {{#crossLink "Sound/activePlugin:property"}}{{/crossLink}}
   * and returned to a preloader like <a href="http://preloadjs.com" target="_blank">PreloadJS</a>.
   * @protected
   * @static
   */
  s._parsePath = function (value) {
    if (typeof(value) != "string") {value = value.toString();}

    var match = value.match(s.FILE_PATTERN);
    if (match == null) {return false;}

    var name = match[4];
    var ext = match[5];
    var c = s.capabilities;
    var i = 0;
    while (!c[ext]) {
      ext = s.alternateExtensions[i++];
      if (i > s.alternateExtensions.length) { return null;} // no extensions are supported
    }
    value = value.replace("."+match[5], "."+ext);

    var ret = {name:name, src:value, extension:ext};
    return ret;
  };

  /**
   * Parse the path of a sound based on properties of src matching with supported extensions.
   * Returns false if none of the properties are supported
   * @method _parseSrc
   * @param {Object} value The paths to an audio source, indexed by extension type.
   * @return {Object} A formatted object that can be registered with the {{#crossLink "Sound/activePlugin:property"}}{{/crossLink}}
   * and returned to a preloader like <a href="http://preloadjs.com" target="_blank">PreloadJS</a>.
   * @protected
   * @static
   */
  s._parseSrc = function (value) {
    var ret = {name:undefined, src:undefined, extension:undefined};
    var c = s.capabilities;

    for (var prop in value) {
      if(value.hasOwnProperty(prop) && c[prop]) {
        ret.src = value[prop];
        ret.extension = prop;
        break;
      }
    }
    if (!ret.src) {return false;} // no matches

    var i = ret.src.lastIndexOf("/");
    if (i != -1) {
      ret.name = ret.src.slice(i+1);
    } else {
      ret.name = ret.src;
    }

    return ret;
  };

  /* ---------------
   Static API.
   --------------- */
  /**
   * Play a sound and get a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to control. If the sound fails to play, a
   * AbstractSoundInstance will still be returned, and have a playState of {{#crossLink "Sound/PLAY_FAILED:property"}}{{/crossLink}}.
   * Note that even on sounds with failed playback, you may still be able to call AbstractSoundInstance {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}},
   * since the failure could be due to lack of available channels. If the src does not have a supported extension or
   * if there is no available plugin, a default AbstractSoundInstance will be returned which will not play any audio, but will not generate errors.
   *
   * <h4>Example</h4>
   *
   *      createjs.Sound.on("fileload", handleLoad);
   *      createjs.Sound.registerSound("myAudioPath/mySound.mp3", "myID", 3);
   *      function handleLoad(event) {
   *        createjs.Sound.play("myID");
   *        // store off AbstractSoundInstance for controlling
   *        var myInstance = createjs.Sound.play("myID", {interrupt: createjs.Sound.INTERRUPT_ANY, loop:-1});
   *      }
   *
   * NOTE to create an audio sprite that has not already been registered, both startTime and duration need to be set.
   * This is only when creating a new audio sprite, not when playing using the id of an already registered audio sprite.
   *
   * <b>Parameters Deprecated</b><br />
   * The parameters for this method are deprecated in favor of a single parameter that is an Object or {{#crossLink "PlayPropsConfig"}}{{/crossLink}}.
   *
   * @method play
   * @param {String} src The src or ID of the audio.
   * @param {String | Object} [interrupt="none"|options] <b>This parameter will be renamed playProps in the next release.</b><br />
   * This parameter can be an instance of {{#crossLink "PlayPropsConfig"}}{{/crossLink}} or an Object that contains any or all optional properties by name,
   * including: interrupt, delay, offset, loop, volume, pan, startTime, and duration (see the above code sample).
   * <br /><strong>OR</strong><br />
   * <b>Deprecated</b> How to interrupt any currently playing instances of audio with the same source,
   * if the maximum number of instances of the sound are already playing. Values are defined as <code>INTERRUPT_TYPE</code>
   * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}.
   * @param {Number} [delay=0] <b>Deprecated</b> The amount of time to delay the start of audio playback, in milliseconds.
   * @param {Number} [offset=0] <b>Deprecated</b> The offset from the start of the audio to begin playback, in milliseconds.
   * @param {Number} [loop=0] <b>Deprecated</b> How many times the audio loops when it reaches the end of playback. The default is 0 (no
   * loops), and -1 can be used for infinite playback.
   * @param {Number} [volume=1] <b>Deprecated</b> The volume of the sound, between 0 and 1. Note that the master volume is applied
   * against the individual volume.
   * @param {Number} [pan=0] <b>Deprecated</b> The left-right pan of the sound (if supported), between -1 (left) and 1 (right).
   * @param {Number} [startTime=null] <b>Deprecated</b> To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds.
   * @param {Number} [duration=null] <b>Deprecated</b> To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds.
   * @return {AbstractSoundInstance} A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} that can be controlled after it is created.
   * @static
   */
  s.play = function (src, interrupt, delay, offset, loop, volume, pan, startTime, duration) {
    var playProps;
    if (interrupt instanceof Object || interrupt instanceof createjs.PlayPropsConfig) {
      playProps = createjs.PlayPropsConfig.create(interrupt);
    } else {
      playProps = createjs.PlayPropsConfig.create({interrupt:interrupt, delay:delay, offset:offset, loop:loop, volume:volume, pan:pan, startTime:startTime, duration:duration});
    }
    var instance = s.createInstance(src, playProps.startTime, playProps.duration);
    var ok = s._playInstance(instance, playProps);
    if (!ok) {instance._playFailed();}
    return instance;
  };

  /**
   * Creates a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} using the passed in src. If the src does not have a
   * supported extension or if there is no available plugin, a default AbstractSoundInstance will be returned that can be
   * called safely but does nothing.
   *
   * <h4>Example</h4>
   *
   *      var myInstance = null;
   *      createjs.Sound.on("fileload", handleLoad);
   *      createjs.Sound.registerSound("myAudioPath/mySound.mp3", "myID", 3);
   *      function handleLoad(event) {
   *        myInstance = createjs.Sound.createInstance("myID");
   *        // alternately we could call the following
   *        myInstance = createjs.Sound.createInstance("myAudioPath/mySound.mp3");
   *      }
   *
   * NOTE to create an audio sprite that has not already been registered, both startTime and duration need to be set.
   * This is only when creating a new audio sprite, not when playing using the id of an already registered audio sprite.
   *
   * @method createInstance
   * @param {String} src The src or ID of the audio.
   * @param {Number} [startTime=null] To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds.
   * @param {Number} [duration=null] To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds.
   * @return {AbstractSoundInstance} A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} that can be controlled after it is created.
   * Unsupported extensions will return the default AbstractSoundInstance.
   * @since 0.4.0
   * @static
   */
  s.createInstance = function (src, startTime, duration) {
    if (!s.initializeDefaultPlugins()) {return new createjs.DefaultSoundInstance(src, startTime, duration);}

    var defaultPlayProps = s._defaultPlayPropsHash[src];  // for audio sprites, which create and store defaults by id
    src = s._getSrcById(src);

    var details = s._parsePath(src.src);

    var instance = null;
    if (details != null && details.src != null) {
      SoundChannel.create(details.src);
      if (startTime == null) {startTime = src.startTime;}
      instance = s.activePlugin.create(details.src, startTime, duration || src.duration);

      defaultPlayProps = defaultPlayProps || s._defaultPlayPropsHash[details.src];
      if(defaultPlayProps) {
        instance.applyPlayProps(defaultPlayProps);
      }
    } else {
      instance = new createjs.DefaultSoundInstance(src, startTime, duration);
    }

    instance.uniqueId = s._lastID++;

    return instance;
  };

  /**
   * Stop all audio (global stop). Stopped audio is reset, and not paused. To play audio that has been stopped,
   * call AbstractSoundInstance {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *     createjs.Sound.stop();
   *
   * @method stop
   * @static
   */
  s.stop = function () {
    var instances = this._instances;
    for (var i = instances.length; i--; ) {
      instances[i].stop();  // NOTE stop removes instance from this._instances
    }
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/volume:property"}}{{/crossLink}} instead.
   *
   * @method setVolume
   * @param {Number} value The master volume value. The acceptable range is 0-1.
   * @static
   * @deprecated
   */
  s.setVolume = function (value) {
    if (Number(value) == null) {return false;}
    value = Math.max(0, Math.min(1, value));
    s._masterVolume = value;
    if (!this.activePlugin || !this.activePlugin.setVolume || !this.activePlugin.setVolume(value)) {
      var instances = this._instances;
      for (var i = 0, l = instances.length; i < l; i++) {
        instances[i].setMasterVolume(value);
      }
    }
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/volume:property"}}{{/crossLink}} instead.
   *
   * @method getVolume
   * @return {Number} The master volume, in a range of 0-1.
   * @static
   * @deprecated
   */
  s.getVolume = function () {
    return this._masterVolume;
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/muted:property"}}{{/crossLink}} instead.
   *
   * @method setMute
   * @param {Boolean} value Whether the audio should be muted or not.
   * @return {Boolean} If the mute was set.
   * @static
   * @since 0.4.0
   * @deprecated
   */
  s.setMute = function (value) {
    if (value == null) {return false;}

    this._masterMute = value;
    if (!this.activePlugin || !this.activePlugin.setMute || !this.activePlugin.setMute(value)) {
      var instances = this._instances;
      for (var i = 0, l = instances.length; i < l; i++) {
        instances[i].setMasterMute(value);
      }
    }
    return true;
  };

  /**
   * Deprecated, please use {{#crossLink "Sound/muted:property"}}{{/crossLink}} instead.
   *
   * @method getMute
   * @return {Boolean} The mute value of Sound.
   * @static
   * @since 0.4.0
   * @deprecated
   */
  s.getMute = function () {
    return this._masterMute;
  };

  /**
   * Set the default playback properties for all new SoundInstances of the passed in src or ID.
   * See {{#crossLink "PlayPropsConfig"}}{{/crossLink}} for available properties.
   *
   * @method setDefaultPlayProps
   * @param {String} src The src or ID used to register the audio.
   * @param {Object | PlayPropsConfig} playProps The playback properties you would like to set.
   * @since 0.6.1
   */
  s.setDefaultPlayProps = function(src, playProps) {
    src = s._getSrcById(src);
    s._defaultPlayPropsHash[s._parsePath(src.src).src] = createjs.PlayPropsConfig.create(playProps);
  };

  /**
   * Get the default playback properties for the passed in src or ID.  These properties are applied to all
   * new SoundInstances.  Returns null if default does not exist.
   *
   * @method getDefaultPlayProps
   * @param {String} src The src or ID used to register the audio.
   * @returns {PlayPropsConfig} returns an existing PlayPropsConfig or null if one does not exist
   * @since 0.6.1
   */
  s.getDefaultPlayProps = function(src) {
    src = s._getSrcById(src);
    return s._defaultPlayPropsHash[s._parsePath(src.src).src];
  };


  /* ---------------
   Internal methods
   --------------- */
  /**
   * Play an instance. This is called by the static API, as well as from plugins. This allows the core class to
   * control delays.
   * @method _playInstance
   * @param {AbstractSoundInstance} instance The {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to start playing.
   * @param {PlayPropsConfig} playProps A PlayPropsConfig object.
   * @return {Boolean} If the sound can start playing. Sounds that fail immediately will return false. Sounds that
   * have a delay will return true, but may still fail to play.
   * @protected
   * @static
   */
  s._playInstance = function (instance, playProps) {
    var defaultPlayProps = s._defaultPlayPropsHash[instance.src] || {};
    if (playProps.interrupt == null) {playProps.interrupt = defaultPlayProps.interrupt || s.defaultInterruptBehavior};
    if (playProps.delay == null) {playProps.delay = defaultPlayProps.delay || 0;}
    if (playProps.offset == null) {playProps.offset = instance.getPosition();}
    if (playProps.loop == null) {playProps.loop = instance.loop;}
    if (playProps.volume == null) {playProps.volume = instance.volume;}
    if (playProps.pan == null) {playProps.pan = instance.pan;}

    if (playProps.delay == 0) {
      var ok = s._beginPlaying(instance, playProps);
      if (!ok) {return false;}
    } else {
      //Note that we can't pass arguments to proxy OR setTimeout (IE only), so just wrap the function call.
      // OJR WebAudio may want to handle this differently, so it might make sense to move this functionality into the plugins in the future
      var delayTimeoutId = setTimeout(function () {
        s._beginPlaying(instance, playProps);
      }, playProps.delay);
      instance.delayTimeoutId = delayTimeoutId;
    }

    this._instances.push(instance);

    return true;
  };

  /**
   * Begin playback. This is called immediately or after delay by {{#crossLink "Sound/playInstance"}}{{/crossLink}}.
   * @method _beginPlaying
   * @param {AbstractSoundInstance} instance A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to begin playback.
   * @param {PlayPropsConfig} playProps A PlayPropsConfig object.
   * @return {Boolean} If the sound can start playing. If there are no available channels, or the instance fails to
   * start, this will return false.
   * @protected
   * @static
   */
  s._beginPlaying = function (instance, playProps) {
    if (!SoundChannel.add(instance, playProps.interrupt)) {
      return false;
    }
    var result = instance._beginPlaying(playProps);
    if (!result) {
      var index = createjs.indexOf(this._instances, instance);
      if (index > -1) {this._instances.splice(index, 1);}
      return false;
    }
    return true;
  };

  /**
   * Get the source of a sound via the ID passed in with a register call. If no ID is found the value is returned
   * instead.
   * @method _getSrcById
   * @param {String} value The ID the sound was registered with.
   * @return {String} The source of the sound if it has been registered with this ID or the value that was passed in.
   * @protected
   * @static
   */
  s._getSrcById = function (value) {
    return s._idHash[value] || {src: value};
  };

  /**
   * A sound has completed playback, been interrupted, failed, or been stopped. This method removes the instance from
   * Sound management. It will be added again, if the sound re-plays. Note that this method is called from the
   * instances themselves.
   * @method _playFinished
   * @param {AbstractSoundInstance} instance The instance that finished playback.
   * @protected
   * @static
   */
  s._playFinished = function (instance) {
    SoundChannel.remove(instance);
    var index = createjs.indexOf(this._instances, instance);
    if (index > -1) {this._instances.splice(index, 1);} // OJR this will always be > -1, there is no way for an instance to exist without being added to this._instances
  };

  createjs.Sound = Sound;

  /**
   * An internal class that manages the number of active {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} instances for
   * each sound type. This method is only used internally by the {{#crossLink "Sound"}}{{/crossLink}} class.
   *
   * The number of sounds is artificially limited by Sound in order to prevent over-saturation of a
   * single sound, as well as to stay within hardware limitations, although the latter may disappear with better
   * browser support.
   *
   * When a sound is played, this class ensures that there is an available instance, or interrupts an appropriate
   * sound that is already playing.
   * #class SoundChannel
   * @param {String} src The source of the instances
   * @param {Number} [max=1] The number of instances allowed
   * @constructor
   * @protected
   */
  function SoundChannel(src, max) {
    this.init(src, max);
  }

  /* ------------
   Static API
   ------------ */
  /**
   * A hash of channel instances indexed by source.
   * #property channels
   * @type {Object}
   * @static
   */
  SoundChannel.channels = {};

  /**
   * Create a sound channel. Note that if the sound channel already exists, this will fail.
   * #method create
   * @param {String} src The source for the channel
   * @param {Number} max The maximum amount this channel holds. The default is {{#crossLink "SoundChannel.maxDefault"}}{{/crossLink}}.
   * @return {Boolean} If the channels were created.
   * @static
   */
  SoundChannel.create = function (src, max) {
    var channel = SoundChannel.get(src);
    if (channel == null) {
      SoundChannel.channels[src] = new SoundChannel(src, max);
      return true;
    }
    return false;
  };
  /**
   * Delete a sound channel, stop and delete all related instances. Note that if the sound channel does not exist, this will fail.
   * #method remove
   * @param {String} src The source for the channel
   * @return {Boolean} If the channels were deleted.
   * @static
   */
  SoundChannel.removeSrc = function (src) {
    var channel = SoundChannel.get(src);
    if (channel == null) {return false;}
    channel._removeAll(); // this stops and removes all active instances
    delete(SoundChannel.channels[src]);
    return true;
  };
  /**
   * Delete all sound channels, stop and delete all related instances.
   * #method removeAll
   * @static
   */
  SoundChannel.removeAll = function () {
    for(var channel in SoundChannel.channels) {
      SoundChannel.channels[channel]._removeAll();  // this stops and removes all active instances
    }
    SoundChannel.channels = {};
  };
  /**
   * Add an instance to a sound channel.
   * #method add
   * @param {AbstractSoundInstance} instance The instance to add to the channel
   * @param {String} interrupt The interrupt value to use. Please see the {{#crossLink "Sound/play"}}{{/crossLink}}
   * for details on interrupt modes.
   * @return {Boolean} The success of the method call. If the channel is full, it will return false.
   * @static
   */
  SoundChannel.add = function (instance, interrupt) {
    var channel = SoundChannel.get(instance.src);
    if (channel == null) {return false;}
    return channel._add(instance, interrupt);
  };
  /**
   * Remove an instance from the channel.
   * #method remove
   * @param {AbstractSoundInstance} instance The instance to remove from the channel
   * @return The success of the method call. If there is no channel, it will return false.
   * @static
   */
  SoundChannel.remove = function (instance) {
    var channel = SoundChannel.get(instance.src);
    if (channel == null) {return false;}
    channel._remove(instance);
    return true;
  };
  /**
   * Get the maximum number of sounds you can have in a channel.
   * #method maxPerChannel
   * @return {Number} The maximum number of sounds you can have in a channel.
   */
  SoundChannel.maxPerChannel = function () {
    return p.maxDefault;
  };
  /**
   * Get a channel instance by its src.
   * #method get
   * @param {String} src The src to use to look up the channel
   * @static
   */
  SoundChannel.get = function (src) {
    return SoundChannel.channels[src];
  };

  var p = SoundChannel.prototype;
  p.constructor = SoundChannel;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


  /**
   * The source of the channel.
   * #property src
   * @type {String}
   */
  p.src = null;

  /**
   * The maximum number of instances in this channel.  -1 indicates no limit
   * #property max
   * @type {Number}
   */
  p.max = null;

  /**
   * The default value to set for max, if it isn't passed in.  Also used if -1 is passed.
   * #property maxDefault
   * @type {Number}
   * @default 100
   * @since 0.4.0
   */
  p.maxDefault = 100;

  /**
   * The current number of active instances.
   * #property length
   * @type {Number}
   */
  p.length = 0;

  /**
   * Initialize the channel.
   * #method init
   * @param {String} src The source of the channel
   * @param {Number} max The maximum number of instances in the channel
   * @protected
   */
  p.init = function (src, max) {
    this.src = src;
    this.max = max || this.maxDefault;
    if (this.max == -1) {this.max = this.maxDefault;}
    this._instances = [];
  };

  /**
   * Get an instance by index.
   * #method get
   * @param {Number} index The index to return.
   * @return {AbstractSoundInstance} The AbstractSoundInstance at a specific instance.
   */
  p._get = function (index) {
    return this._instances[index];
  };

  /**
   * Add a new instance to the channel.
   * #method add
   * @param {AbstractSoundInstance} instance The instance to add.
   * @return {Boolean} The success of the method call. If the channel is full, it will return false.
   */
  p._add = function (instance, interrupt) {
    if (!this._getSlot(interrupt, instance)) {return false;}
    this._instances.push(instance);
    this.length++;
    return true;
  };

  /**
   * Remove an instance from the channel, either when it has finished playing, or it has been interrupted.
   * #method remove
   * @param {AbstractSoundInstance} instance The instance to remove
   * @return {Boolean} The success of the remove call. If the instance is not found in this channel, it will
   * return false.
   */
  p._remove = function (instance) {
    var index = createjs.indexOf(this._instances, instance);
    if (index == -1) {return false;}
    this._instances.splice(index, 1);
    this.length--;
    return true;
  };

  /**
   * Stop playback and remove all instances from the channel.  Usually in response to a delete call.
   * #method removeAll
   */
  p._removeAll = function () {
    // Note that stop() removes the item from the list
    for (var i=this.length-1; i>=0; i--) {
      this._instances[i].stop();
    }
  };

  /**
   * Get an available slot depending on interrupt value and if slots are available.
   * #method getSlot
   * @param {String} interrupt The interrupt value to use.
   * @param {AbstractSoundInstance} instance The sound instance that will go in the channel if successful.
   * @return {Boolean} Determines if there is an available slot. Depending on the interrupt mode, if there are no slots,
   * an existing AbstractSoundInstance may be interrupted. If there are no slots, this method returns false.
   */
  p._getSlot = function (interrupt, instance) {
    var target, replacement;

    if (interrupt != Sound.INTERRUPT_NONE) {
      // First replacement candidate
      replacement = this._get(0);
      if (replacement == null) {
        return true;
      }
    }

    for (var i = 0, l = this.max; i < l; i++) {
      target = this._get(i);

      // Available Space
      if (target == null) {
        return true;
      }

      // Audio is complete or not playing
      if (target.playState == Sound.PLAY_FINISHED ||
        target.playState == Sound.PLAY_INTERRUPTED ||
        target.playState == Sound.PLAY_FAILED) {
        replacement = target;
        break;
      }

      if (interrupt == Sound.INTERRUPT_NONE) {
        continue;
      }

      // Audio is a better candidate than the current target, according to playhead
      if ((interrupt == Sound.INTERRUPT_EARLY && target.getPosition() < replacement.getPosition()) ||
        (interrupt == Sound.INTERRUPT_LATE && target.getPosition() > replacement.getPosition())) {
          replacement = target;
      }
    }

    if (replacement != null) {
      replacement._interrupt();
      this._remove(replacement);
      return true;
    }
    return false;
  };

  p.toString = function () {
    return "[Sound SoundChannel]";
  };
  // do not add SoundChannel to namespace

}());

//##############################################################################
// AbstractSoundInstance.js
//##############################################################################

/**
 * A AbstractSoundInstance is created when any calls to the Sound API method {{#crossLink "Sound/play"}}{{/crossLink}} or
 * {{#crossLink "Sound/createInstance"}}{{/crossLink}} are made. The AbstractSoundInstance is returned by the active plugin
 * for control by the user.
 *
 * <h4>Example</h4>
 *
 *      var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3");
 *
 * A number of additional parameters provide a quick way to determine how a sound is played. Please see the Sound
 * API method {{#crossLink "Sound/play"}}{{/crossLink}} for a list of arguments.
 *
 * Once a AbstractSoundInstance is created, a reference can be stored that can be used to control the audio directly through
 * the AbstractSoundInstance. If the reference is not stored, the AbstractSoundInstance will play out its audio (and any loops), and
 * is then de-referenced from the {{#crossLink "Sound"}}{{/crossLink}} class so that it can be cleaned up. If audio
 * playback has completed, a simple call to the {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}} instance method
 * will rebuild the references the Sound class need to control it.
 *
 *      var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3", {loop:2});
 *      myInstance.on("loop", handleLoop);
 *      function handleLoop(event) {
 *          myInstance.volume = myInstance.volume * 0.5;
 *      }
 *
 * Events are dispatched from the instance to notify when the sound has completed, looped, or when playback fails
 *
 *      var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3");
 *      myInstance.on("complete", handleComplete);
 *      myInstance.on("loop", handleLoop);
 *      myInstance.on("failed", handleFailed);
 *
 *
 * @class AbstractSoundInstance
 * @param {String} src The path to and file name of the sound.
 * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds.
 * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds.
 * @param {Object} playbackResource Any resource needed by plugin to support audio playback.
 * @extends EventDispatcher
 * @constructor
 */

(function () {
  "use strict";


// Constructor:
  var AbstractSoundInstance = function (src, startTime, duration, playbackResource) {
    this.EventDispatcher_constructor();


  // public properties:
    /**
     * The source of the sound.
     * @property src
     * @type {String}
     * @default null
     */
    this.src = src;

    /**
     * The unique ID of the instance. This is set by {{#crossLink "Sound"}}{{/crossLink}}.
     * @property uniqueId
     * @type {String} | Number
     * @default -1
     */
    this.uniqueId = -1;

    /**
     * The play state of the sound. Play states are defined as constants on {{#crossLink "Sound"}}{{/crossLink}}.
     * @property playState
     * @type {String}
     * @default null
     */
    this.playState = null;

    /**
     * A Timeout created by {{#crossLink "Sound"}}{{/crossLink}} when this AbstractSoundInstance is played with a delay.
     * This allows AbstractSoundInstance to remove the delay if stop, pause, or cleanup are called before playback begins.
     * @property delayTimeoutId
     * @type {timeoutVariable}
     * @default null
     * @protected
     * @since 0.4.0
     */
    this.delayTimeoutId = null;
    // TODO consider moving delay into AbstractSoundInstance so it can be handled by plugins


  // private properties
  // Getter / Setter Properties
    // OJR TODO find original reason that we didn't use defined functions.  I think it was performance related
    /**
     * The volume of the sound, between 0 and 1.
     *
     * The actual output volume of a sound can be calculated using:
     * <code>myInstance.volume * createjs.Sound.getVolume();</code>
     *
     * @property volume
     * @type {Number}
     * @default 1
     */
    this._volume =  1;
    Object.defineProperty(this, "volume", {
      get: this.getVolume,
      set: this.setVolume
    });

    /**
     * The pan of the sound, between -1 (left) and 1 (right). Note that pan is not supported by HTML Audio.
     *
     * <br />Note in WebAudioPlugin this only gives us the "x" value of what is actually 3D audio.
     *
     * @property pan
     * @type {Number}
     * @default 0
     */
    this._pan =  0;
    Object.defineProperty(this, "pan", {
      get: this.getPan,
      set: this.setPan
    });

    /**
     * Audio sprite property used to determine the starting offset.
     * @property startTime
     * @type {Number}
     * @default 0
     * @since 0.6.1
     */
    this._startTime = Math.max(0, startTime || 0);
    Object.defineProperty(this, "startTime", {
      get: this.getStartTime,
      set: this.setStartTime
    });

    /**
     * The length of the audio clip, in milliseconds.
     *
     * @property duration
     * @type {Number}
     * @default 0
     * @since 0.6.0
     */
    this._duration = Math.max(0, duration || 0);
    Object.defineProperty(this, "duration", {
      get: this.getDuration,
      set: this.setDuration
    });

    /**
     * Object that holds plugin specific resource need for audio playback.
     * This is set internally by the plugin.  For example, WebAudioPlugin will set an array buffer,
     * HTMLAudioPlugin will set a tag, FlashAudioPlugin will set a flash reference.
     *
     * @property playbackResource
     * @type {Object}
     * @default null
     */
    this._playbackResource = null;
    Object.defineProperty(this, "playbackResource", {
      get: this.getPlaybackResource,
      set: this.setPlaybackResource
    });
    if(playbackResource !== false && playbackResource !== true) { this.setPlaybackResource(playbackResource); }

    /**
     * The position of the playhead in milliseconds. This can be set while a sound is playing, paused, or stopped.
     *
     * @property position
     * @type {Number}
     * @default 0
     * @since 0.6.0
     */
    this._position = 0;
    Object.defineProperty(this, "position", {
      get: this.getPosition,
      set: this.setPosition
    });

    /**
     * The number of play loops remaining. Negative values will loop infinitely.
     *
     * @property loop
     * @type {Number}
     * @default 0
     * @public
     * @since 0.6.0
     */
    this._loop = 0;
    Object.defineProperty(this, "loop", {
      get: this.getLoop,
      set: this.setLoop
    });

    /**
     * Determines if the audio is currently muted.
     *
     * @property muted
     * @type {Boolean}
     * @default false
     * @since 0.6.0
     */
    this._muted = false;
    Object.defineProperty(this, "muted", {
      get: this.getMuted,
      set: this.setMuted
    });

    /**
     * Tells you if the audio is currently paused.
     *
     * @property paused
     * @type {Boolean}
     */
    this._paused = false;
    Object.defineProperty(this, "paused", {
      get: this.getPaused,
      set: this.setPaused
    });


  // Events
    /**
     * The event that is fired when playback has started successfully.
     * @event succeeded
     * @param {Object} target The object that dispatched the event.
     * @param {String} type The event type.
     * @since 0.4.0
     */

    /**
     * The event that is fired when playback is interrupted. This happens when another sound with the same
     * src property is played using an interrupt value that causes this instance to stop playing.
     * @event interrupted
     * @param {Object} target The object that dispatched the event.
     * @param {String} type The event type.
     * @since 0.4.0
     */

    /**
     * The event that is fired when playback has failed. This happens when there are too many channels with the same
     * src property already playing (and the interrupt value doesn't cause an interrupt of another instance), or
     * the sound could not be played, perhaps due to a 404 error.
     * @event failed
     * @param {Object} target The object that dispatched the event.
     * @param {String} type The event type.
     * @since 0.4.0
     */

    /**
     * The event that is fired when a sound has completed playing but has loops remaining.
     * @event loop
     * @param {Object} target The object that dispatched the event.
     * @param {String} type The event type.
     * @since 0.4.0
     */

    /**
     * The event that is fired when playback completes. This means that the sound has finished playing in its
     * entirety, including its loop iterations.
     * @event complete
     * @param {Object} target The object that dispatched the event.
     * @param {String} type The event type.
     * @since 0.4.0
     */
  };

  var p = createjs.extend(AbstractSoundInstance, createjs.EventDispatcher);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// Public Methods:
  /**
   * Play an instance. This method is intended to be called on SoundInstances that already exist (created
   * with the Sound API {{#crossLink "Sound/createInstance"}}{{/crossLink}} or {{#crossLink "Sound/play"}}{{/crossLink}}).
   *
   * <h4>Example</h4>
   *
   *      var myInstance = createjs.Sound.createInstance(mySrc);
   *      myInstance.play({interrupt:createjs.Sound.INTERRUPT_ANY, loop:2, pan:0.5});
   *
   * Note that if this sound is already playing, this call will still set the passed in parameters.

   * <b>Parameters Deprecated</b><br />
   * The parameters for this method are deprecated in favor of a single parameter that is an Object or {{#crossLink "PlayPropsConfig"}}{{/crossLink}}.
   *
   * @method play
   * @param {String | Object} [interrupt="none"|options] <b>This parameter will be renamed playProps in the next release.</b><br />
   * This parameter can be an instance of {{#crossLink "PlayPropsConfig"}}{{/crossLink}} or an Object that contains any or all optional properties by name,
   * including: interrupt, delay, offset, loop, volume, pan, startTime, and duration (see the above code sample).
   * <br /><strong>OR</strong><br />
   * <b>Deprecated</b> How to interrupt any currently playing instances of audio with the same source,
   * if the maximum number of instances of the sound are already playing. Values are defined as <code>INTERRUPT_TYPE</code>
   * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}.
   * @param {Number} [delay=0] <b>Deprecated</b> The amount of time to delay the start of audio playback, in milliseconds.
   * @param {Number} [offset=0] <b>Deprecated</b> The offset from the start of the audio to begin playback, in milliseconds.
   * @param {Number} [loop=0] <b>Deprecated</b> How many times the audio loops when it reaches the end of playback. The default is 0 (no
   * loops), and -1 can be used for infinite playback.
   * @param {Number} [volume=1] <b>Deprecated</b> The volume of the sound, between 0 and 1. Note that the master volume is applied
   * against the individual volume.
   * @param {Number} [pan=0] <b>Deprecated</b> The left-right pan of the sound (if supported), between -1 (left) and 1 (right).
   * Note that pan is not supported for HTML Audio.
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   */
  p.play = function (interrupt, delay, offset, loop, volume, pan) {
    var playProps;
    if (interrupt instanceof Object || interrupt instanceof createjs.PlayPropsConfig) {
      playProps = createjs.PlayPropsConfig.create(interrupt);
    } else {
      playProps = createjs.PlayPropsConfig.create({interrupt:interrupt, delay:delay, offset:offset, loop:loop, volume:volume, pan:pan});
    }

    if (this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this.applyPlayProps(playProps);
      if (this._paused) { this.setPaused(false); }
      return;
    }
    this._cleanUp();
    createjs.Sound._playInstance(this, playProps);  // make this an event dispatch??
    return this;
  };

  /**
   * Stop playback of the instance. Stopped sounds will reset their position to 0, and calls to {{#crossLink "AbstractSoundInstance/resume"}}{{/crossLink}}
   * will fail.  To start playback again, call {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}}.
   *
   * <h4>Example</h4>
   *
   *     myInstance.stop();
   *
   * @method stop
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   */
  p.stop = function () {
    this._position = 0;
    this._paused = false;
    this._handleStop();
    this._cleanUp();
    this.playState = createjs.Sound.PLAY_FINISHED;
    return this;
  };

  /**
   * Remove all external references and resources from AbstractSoundInstance.  Note this is irreversible and AbstractSoundInstance will no longer work
   * @method destroy
   * @since 0.6.0
   */
  p.destroy = function() {
    this._cleanUp();
    this.src = null;
    this.playbackResource = null;

    this.removeAllEventListeners();
  };

  /**
   * Takes an PlayPropsConfig or Object with the same properties and sets them on this instance.
   * @method applyPlayProps
   * @param {PlayPropsConfig | Object} playProps A PlayPropsConfig or object containing the same properties.
   * @since 0.6.1
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   */
  p.applyPlayProps = function(playProps) {
    if (playProps.offset != null) { this.setPosition(playProps.offset) }
    if (playProps.loop != null) { this.setLoop(playProps.loop); }
    if (playProps.volume != null) { this.setVolume(playProps.volume); }
    if (playProps.pan != null) { this.setPan(playProps.pan); }
    if (playProps.startTime != null) {
      this.setStartTime(playProps.startTime);
      this.setDuration(playProps.duration);
    }
    return this;
  };

  p.toString = function () {
    return "[AbstractSoundInstance]";
  };

// get/set methods that allow support for IE8
  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/paused:property"}}{{/crossLink}} directly as a property,
   *
   * @deprecated
   * @method getPaused
   * @returns {boolean} If the instance is currently paused
   * @since 0.6.0
   */
  p.getPaused = function() {
    return this._paused;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/paused:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setPaused
   * @param {boolean} value
   * @since 0.6.0
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   */
  p.setPaused = function (value) {
    if ((value !== true && value !== false) || this._paused == value) {return;}
    if (value == true && this.playState != createjs.Sound.PLAY_SUCCEEDED) {return;}
    this._paused = value;
    if(value) {
      this._pause();
    } else {
      this._resume();
    }
    clearTimeout(this.delayTimeoutId);
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setVolume
   * @param {Number} value The volume to set, between 0 and 1.
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   */
  p.setVolume = function (value) {
    if (value == this._volume) { return this; }
    this._volume = Math.max(0, Math.min(1, value));
    if (!this._muted) {
      this._updateVolume();
    }
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getVolume
   * @return {Number} The current volume of the sound instance.
   */
  p.getVolume = function () {
    return this._volume;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setMuted
   * @param {Boolean} value If the sound should be muted.
   * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls.
   * @since 0.6.0
   */
  p.setMuted = function (value) {
    if (value !== true && value !== false) {return;}
    this._muted = value;
    this._updateVolume();
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getMuted
   * @return {Boolean} If the sound is muted.
   * @since 0.6.0
   */
  p.getMuted = function () {
    return this._muted;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/pan:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setPan
   * @param {Number} value The pan value, between -1 (left) and 1 (right).
   * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
   */
  p.setPan = function (value) {
    if(value == this._pan) { return this; }
    this._pan = Math.max(-1, Math.min(1, value));
    this._updatePan();
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/pan:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getPan
   * @return {Number} The value of the pan, between -1 (left) and 1 (right).
   */
  p.getPan = function () {
    return this._pan;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/position:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getPosition
   * @return {Number} The position of the playhead in the sound, in milliseconds.
   */
  p.getPosition = function () {
    if (!this._paused && this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this._position = this._calculateCurrentPosition();
    }
    return this._position;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/position:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setPosition
   * @param {Number} value The position to place the playhead, in milliseconds.
   * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
   */
  p.setPosition = function (value) {
    this._position = Math.max(0, value);
    if (this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this._updatePosition();
    }
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/startTime:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getStartTime
   * @return {Number} The startTime of the sound instance in milliseconds.
   */
  p.getStartTime = function () {
    return this._startTime;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/startTime:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setStartTime
   * @param {number} value The new startTime time in milli seconds.
   * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
   */
  p.setStartTime = function (value) {
    if (value == this._startTime) { return this; }
    this._startTime = Math.max(0, value || 0);
    this._updateStartTime();
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/duration:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getDuration
   * @return {Number} The duration of the sound instance in milliseconds.
   */
  p.getDuration = function () {
    return this._duration;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/duration:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setDuration
   * @param {number} value The new duration time in milli seconds.
   * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
   * @since 0.6.0
   */
  p.setDuration = function (value) {
    if (value == this._duration) { return this; }
    this._duration = Math.max(0, value || 0);
    this._updateDuration();
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/playbackResource:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setPlayback
   * @param {Object} value The new playback resource.
   * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
   * @since 0.6.0
   **/
  p.setPlaybackResource = function (value) {
    this._playbackResource = value;
    if (this._duration == 0) { this._setDurationFromSource(); }
    return this;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/playbackResource:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method setPlayback
   * @param {Object} value The new playback resource.
   * @return {Object} playback resource used for playing audio
   * @since 0.6.0
   **/
  p.getPlaybackResource = function () {
    return this._playbackResource;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/loop:property"}}{{/crossLink}} directly as a property
   *
   * @deprecated
   * @method getLoop
   * @return {number}
   * @since 0.6.0
   **/
  p.getLoop = function () {
    return this._loop;
  };

  /**
   * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/loop:property"}}{{/crossLink}} directly as a property,
   *
   * @deprecated
   * @method setLoop
   * @param {number} value The number of times to loop after play.
   * @since 0.6.0
   */
  p.setLoop = function (value) {
    if(this._playbackResource != null) {
      // remove looping
      if (this._loop != 0 && value == 0) {
        this._removeLooping(value);
      }
      // add looping
      else if (this._loop == 0 && value != 0) {
        this._addLooping(value);
      }
    }
    this._loop = value;
  };


// Private Methods:
  /**
   * A helper method that dispatches all events for AbstractSoundInstance.
   * @method _sendEvent
   * @param {String} type The event type
   * @protected
   */
  p._sendEvent = function (type) {
    var event = new createjs.Event(type);
    this.dispatchEvent(event);
  };

  /**
   * Clean up the instance. Remove references and clean up any additional properties such as timers.
   * @method _cleanUp
   * @protected
   */
  p._cleanUp = function () {
    clearTimeout(this.delayTimeoutId); // clear timeout that plays delayed sound
    this._handleCleanUp();
    this._paused = false;

    createjs.Sound._playFinished(this); // TODO change to an event
  };

  /**
   * The sound has been interrupted.
   * @method _interrupt
   * @protected
   */
  p._interrupt = function () {
    this._cleanUp();
    this.playState = createjs.Sound.PLAY_INTERRUPTED;
    this._sendEvent("interrupted");
  };

  /**
   * Called by the Sound class when the audio is ready to play (delay has completed). Starts sound playing if the
   * src is loaded, otherwise playback will fail.
   * @method _beginPlaying
   * @param {PlayPropsConfig} playProps A PlayPropsConfig object.
   * @return {Boolean} If playback succeeded.
   * @protected
   */
  // OJR FlashAudioSoundInstance overwrites
  p._beginPlaying = function (playProps) {
    this.setPosition(playProps.offset);
    this.setLoop(playProps.loop);
    this.setVolume(playProps.volume);
    this.setPan(playProps.pan);
    if (playProps.startTime != null) {
      this.setStartTime(playProps.startTime);
      this.setDuration(playProps.duration);
    }

    if (this._playbackResource != null && this._position < this._duration) {
      this._paused = false;
      this._handleSoundReady();
      this.playState = createjs.Sound.PLAY_SUCCEEDED;
      this._sendEvent("succeeded");
      return true;
    } else {
      this._playFailed();
      return false;
    }
  };

  /**
   * Play has failed, which can happen for a variety of reasons.
   * Cleans up instance and dispatches failed event
   * @method _playFailed
   * @private
   */
  p._playFailed = function () {
    this._cleanUp();
    this.playState = createjs.Sound.PLAY_FAILED;
    this._sendEvent("failed");
  };

  /**
   * Audio has finished playing. Manually loop it if required.
   * @method _handleSoundComplete
   * @param event
   * @protected
   */
  p._handleSoundComplete = function (event) {
    this._position = 0;  // have to set this as it can be set by pause during playback

    if (this._loop != 0) {
      this._loop--;  // NOTE this introduces a theoretical limit on loops = float max size x 2 - 1
      this._handleLoop();
      this._sendEvent("loop");
      return;
    }

    this._cleanUp();
    this.playState = createjs.Sound.PLAY_FINISHED;
    this._sendEvent("complete");
  };

// Plugin specific code
  /**
   * Handles starting playback when the sound is ready for playing.
   * @method _handleSoundReady
   * @protected
   */
  p._handleSoundReady = function () {
    // plugin specific code
  };

  /**
   * Internal function used to update the volume based on the instance volume, master volume, instance mute value,
   * and master mute value.
   * @method _updateVolume
   * @protected
   */
  p._updateVolume = function () {
    // plugin specific code
  };

  /**
   * Internal function used to update the pan
   * @method _updatePan
   * @protected
   * @since 0.6.0
   */
  p._updatePan = function () {
    // plugin specific code
  };

  /**
   * Internal function used to update the startTime of the audio.
   * @method _updateStartTime
   * @protected
   * @since 0.6.1
   */
  p._updateStartTime = function () {
    // plugin specific code
  };

  /**
   * Internal function used to update the duration of the audio.
   * @method _updateDuration
   * @protected
   * @since 0.6.0
   */
  p._updateDuration = function () {
    // plugin specific code
  };

  /**
   * Internal function used to get the duration of the audio from the source we'll be playing.
   * @method _updateDuration
   * @protected
   * @since 0.6.0
   */
  p._setDurationFromSource = function () {
    // plugin specific code
  };

  /**
   * Internal function that calculates the current position of the playhead and sets this._position to that value
   * @method _calculateCurrentPosition
   * @protected
   * @since 0.6.0
   */
  p._calculateCurrentPosition = function () {
    // plugin specific code that sets this.position
  };

  /**
   * Internal function used to update the position of the playhead.
   * @method _updatePosition
   * @protected
   * @since 0.6.0
   */
  p._updatePosition = function () {
    // plugin specific code
  };

  /**
   * Internal function called when looping is removed during playback.
   * @method _removeLooping
   * @param {number} value The number of times to loop after play.
   * @protected
   * @since 0.6.0
   */
  p._removeLooping = function (value) {
    // plugin specific code
  };

  /**
   * Internal function called when looping is added during playback.
   * @method _addLooping
   * @param {number} value The number of times to loop after play.
   * @protected
   * @since 0.6.0
   */
  p._addLooping = function (value) {
    // plugin specific code
  };

  /**
   * Internal function called when pausing playback
   * @method _pause
   * @protected
   * @since 0.6.0
   */
  p._pause = function () {
    // plugin specific code
  };

  /**
   * Internal function called when resuming playback
   * @method _resume
   * @protected
   * @since 0.6.0
   */
  p._resume = function () {
    // plugin specific code
  };

  /**
   * Internal function called when stopping playback
   * @method _handleStop
   * @protected
   * @since 0.6.0
   */
  p._handleStop = function() {
    // plugin specific code
  };

  /**
   * Internal function called when AbstractSoundInstance is being cleaned up
   * @method _handleCleanUp
   * @protected
   * @since 0.6.0
   */
  p._handleCleanUp = function() {
    // plugin specific code
  };

  /**
   * Internal function called when AbstractSoundInstance has played to end and is looping
   * @method _handleLoop
   * @protected
   * @since 0.6.0
   */
  p._handleLoop = function () {
    // plugin specific code
  };

  createjs.AbstractSoundInstance = createjs.promote(AbstractSoundInstance, "EventDispatcher");
  createjs.DefaultSoundInstance = createjs.AbstractSoundInstance; // used when no plugin is supported
}());

//##############################################################################
// AbstractPlugin.js
//##############################################################################

(function () {
  "use strict";


// constructor:
  /**
   * A default plugin class used as a base for all other plugins.
   * @class AbstractPlugin
   * @constructor
   * @since 0.6.0
   */

  var AbstractPlugin = function () {
  // private properties:
    /**
     * The capabilities of the plugin.
     * method and is used internally.
     * @property _capabilities
     * @type {Object}
     * @default null
     * @protected
     * @static
     */
    this._capabilities = null;

    /**
     * Object hash indexed by the source URI of all created loaders, used to properly destroy them if sources are removed.
     * @type {Object}
     * @protected
     */
    this._loaders = {};

    /**
     * Object hash indexed by the source URI of each file to indicate if an audio source has begun loading,
     * is currently loading, or has completed loading.  Can be used to store non boolean data after loading
     * is complete (for example arrayBuffers for web audio).
     * @property _audioSources
     * @type {Object}
     * @protected
     */
    this._audioSources = {};

    /**
     * Object hash indexed by the source URI of all created SoundInstances, updates the playbackResource if it loads after they are created,
     * and properly destroy them if sources are removed
     * @type {Object}
     * @protected
     */
    this._soundInstances = {};

    /**
     * The internal master volume value of the plugin.
     * @property _volume
     * @type {Number}
     * @default 1
     * @protected
     */
    this._volume = 1;

    /**
     * A reference to a loader class used by a plugin that must be set.
     * @type {Object}
     * @protected
     */
    this._loaderClass;

    /**
     * A reference to an AbstractSoundInstance class used by a plugin that must be set.
     * @type {Object}
     * @protected;
     */
    this._soundInstanceClass;
  };
  var p = AbstractPlugin.prototype;

  /**
   * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
   * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
   * for details.
   *
   * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
   *
   * @method initialize
   * @protected
   * @deprecated
   */
  // p.initialize = function() {}; // searchable for devs wondering where it is.


// Static Properties:
// NOTE THESE PROPERTIES NEED TO BE ADDED TO EACH PLUGIN
  /**
   * The capabilities of the plugin. This is generated via the _generateCapabilities method and is used internally.
   * @property _capabilities
   * @type {Object}
   * @default null
   * @protected
   * @static
   */
  AbstractPlugin._capabilities = null;

  /**
   * Determine if the plugin can be used in the current browser/OS.
   * @method isSupported
   * @return {Boolean} If the plugin can be initialized.
   * @static
   */
  AbstractPlugin.isSupported = function () {
    return true;
  };


// public methods:
  /**
   * Pre-register a sound for preloading and setup. This is called by {{#crossLink "Sound"}}{{/crossLink}}.
   * Note all plugins provide a <code>Loader</code> instance, which <a href="http://preloadjs.com" target="_blank">PreloadJS</a>
   * can use to assist with preloading.
   * @method register
   * @param {String} loadItem An Object containing the source of the audio
   * Note that not every plugin will manage this value.
   * @return {Object} A result object, containing a "tag" for preloading purposes.
   */
  p.register = function (loadItem) {
    var loader = this._loaders[loadItem.src];
    if(loader && !loader.canceled) {return this._loaders[loadItem.src];}  // already loading/loaded this, so don't load twice
    // OJR potential issue that we won't be firing loaded event, might need to trigger if this is already loaded?
    this._audioSources[loadItem.src] = true;
    this._soundInstances[loadItem.src] = [];
    loader = new this._loaderClass(loadItem);
    loader.on("complete", createjs.proxy(this._handlePreloadComplete, this));
    this._loaders[loadItem.src] = loader;
    return loader;
  };

  // note sound calls register before calling preload
  /**
   * Internally preload a sound.
   * @method preload
   * @param {Loader} loader The sound URI to load.
   */
  p.preload = function (loader) {
    loader.on("error", createjs.proxy(this._handlePreloadError, this));
    loader.load();
  };

  /**
   * Checks if preloading has started for a specific source. If the source is found, we can assume it is loading,
   * or has already finished loading.
   * @method isPreloadStarted
   * @param {String} src The sound URI to check.
   * @return {Boolean}
   */
  p.isPreloadStarted = function (src) {
    return (this._audioSources[src] != null);
  };

  /**
   * Checks if preloading has finished for a specific source.
   * @method isPreloadComplete
   * @param {String} src The sound URI to load.
   * @return {Boolean}
   */
  p.isPreloadComplete = function (src) {
    return (!(this._audioSources[src] == null || this._audioSources[src] == true));
  };

  /**
   * Remove a sound added using {{#crossLink "WebAudioPlugin/register"}}{{/crossLink}}. Note this does not cancel a preload.
   * @method removeSound
   * @param {String} src The sound URI to unload.
   */
  p.removeSound = function (src) {
    if (!this._soundInstances[src]) { return; }
    for (var i = this._soundInstances[src].length; i--; ) {
      var item = this._soundInstances[src][i];
      item.destroy();
    }
    delete(this._soundInstances[src]);
    delete(this._audioSources[src]);
    if(this._loaders[src]) { this._loaders[src].destroy(); }
    delete(this._loaders[src]);
  };

  /**
   * Remove all sounds added using {{#crossLink "WebAudioPlugin/register"}}{{/crossLink}}. Note this does not cancel a preload.
   * @method removeAllSounds
   * @param {String} src The sound URI to unload.
   */
  p.removeAllSounds = function () {
    for(var key in this._audioSources) {
      this.removeSound(key);
    }
  };

  /**
   * Create a sound instance. If the sound has not been preloaded, it is internally preloaded here.
   * @method create
   * @param {String} src The sound source to use.
   * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds.
   * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds.
   * @return {AbstractSoundInstance} A sound instance for playback and control.
   */
  p.create = function (src, startTime, duration) {
    if (!this.isPreloadStarted(src)) {
      this.preload(this.register(src));
    }
    var si = new this._soundInstanceClass(src, startTime, duration, this._audioSources[src]);
    this._soundInstances[src].push(si);
    return si;
  };

  // if a plugin does not support volume and mute, it should set these to null
  /**
   * Set the master volume of the plugin, which affects all SoundInstances.
   * @method setVolume
   * @param {Number} value The volume to set, between 0 and 1.
   * @return {Boolean} If the plugin processes the setVolume call (true). The Sound class will affect all the
   * instances manually otherwise.
   */
  p.setVolume = function (value) {
    this._volume = value;
    this._updateVolume();
    return true;
  };

  /**
   * Get the master volume of the plugin, which affects all SoundInstances.
   * @method getVolume
   * @return {Number} The volume level, between 0 and 1.
   */
  p.getVolume = function () {
    return this._volume;
  };

  /**
   * Mute all sounds via the plugin.
   * @method setMute
   * @param {Boolean} value If all sound should be muted or not. Note that plugin-level muting just looks up
   * the mute value of Sound {{#crossLink "Sound/getMute"}}{{/crossLink}}, so this property is not used here.
   * @return {Boolean} If the mute call succeeds.
   */
  p.setMute = function (value) {
    this._updateVolume();
    return true;
  };

  // plugins should overwrite this method
  p.toString = function () {
    return "[AbstractPlugin]";
  };


// private methods:
  /**
   * Handles internal preload completion.
   * @method _handlePreloadComplete
   * @protected
   */
  p._handlePreloadComplete = function (event) {
    var src = event.target.getItem().src;
    this._audioSources[src] = event.result;
    for (var i = 0, l = this._soundInstances[src].length; i < l; i++) {
      var item = this._soundInstances[src][i];
      item.setPlaybackResource(this._audioSources[src]);
      // ToDo consider adding play call here if playstate == playfailed
    }
  };

  /**
   * Handles internal preload erros
   * @method _handlePreloadError
   * @param event
   * @protected
   */
  p._handlePreloadError = function(event) {
    //delete(this._audioSources[src]);
  };

  /**
   * Set the gain value for master audio. Should not be called externally.
   * @method _updateVolume
   * @protected
   */
  p._updateVolume = function () {
    // Plugin Specific code
  };

  createjs.AbstractPlugin = AbstractPlugin;
}());

//##############################################################################
// WebAudioLoader.js
//##############################################################################

(function () {
  "use strict";

  /**
   * Loader provides a mechanism to preload Web Audio content via PreloadJS or internally. Instances are returned to
   * the preloader, and the load method is called when the asset needs to be requested.
   *
   * @class WebAudioLoader
   * @param {String} loadItem The item to be loaded
   * @extends XHRRequest
   * @protected
   */
  function Loader(loadItem) {
    this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.SOUND);

  };
  var p = createjs.extend(Loader, createjs.AbstractLoader);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


  /**
   * web audio context required for decoding audio
   * @property context
   * @type {AudioContext}
   * @static
   */
  Loader.context = null;


// public methods
  p.toString = function () {
    return "[WebAudioLoader]";
  };


// private methods
  p._createRequest = function() {
    this._request = new createjs.XHRRequest(this._item, false);
    this._request.setResponseType("arraybuffer");
  };

  p._sendComplete = function (event) {
    // OJR we leave this wrapped in Loader because we need to reference src and the handler only receives a single argument, the decodedAudio
    Loader.context.decodeAudioData(this._rawResult,
           createjs.proxy(this._handleAudioDecoded, this),
           createjs.proxy(this._sendError, this));
  };


  /**
  * The audio has been decoded.
  * @method handleAudioDecoded
  * @param decoded
  * @protected
  */
  p._handleAudioDecoded = function (decodedAudio) {
    this._result = decodedAudio;
    this.AbstractLoader__sendComplete();
  };

  createjs.WebAudioLoader = createjs.promote(Loader, "AbstractLoader");
}());

//##############################################################################
// WebAudioSoundInstance.js
//##############################################################################

/**
 * WebAudioSoundInstance extends the base api of {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} and is used by
 * {{#crossLink "WebAudioPlugin"}}{{/crossLink}}.
 *
 * WebAudioSoundInstance exposes audioNodes for advanced users.
 *
 * @param {String} src The path to and file name of the sound.
 * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds.
 * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds.
 * @param {Object} playbackResource Any resource needed by plugin to support audio playback.
 * @class WebAudioSoundInstance
 * @extends AbstractSoundInstance
 * @constructor
 */
(function () {
  "use strict";

  function WebAudioSoundInstance(src, startTime, duration, playbackResource) {
    this.AbstractSoundInstance_constructor(src, startTime, duration, playbackResource);


// public properties
    /**
     * NOTE this is only intended for use by advanced users.
     * <br />GainNode for controlling <code>WebAudioSoundInstance</code> volume. Connected to the {{#crossLink "WebAudioSoundInstance/destinationNode:property"}}{{/crossLink}}.
     * @property gainNode
     * @type {AudioGainNode}
     * @since 0.4.0
     *
     */
    this.gainNode = s.context.createGain();

    /**
     * NOTE this is only intended for use by advanced users.
     * <br />A panNode allowing left and right audio channel panning only. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/gainNode:property"}}{{/crossLink}}.
     * @property panNode
     * @type {AudioPannerNode}
     * @since 0.4.0
     */
    this.panNode = s.context.createPanner();
    this.panNode.panningModel = s._panningModel;
    this.panNode.connect(this.gainNode);

    /**
     * NOTE this is only intended for use by advanced users.
     * <br />sourceNode is the audio source. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/panNode:property"}}{{/crossLink}}.
     * @property sourceNode
     * @type {AudioNode}
     * @since 0.4.0
     *
     */
    this.sourceNode = null;


// private properties
    /**
     * Timeout that is created internally to handle sound playing to completion.
     * Stored so we can remove it when stop, pause, or cleanup are called
     * @property _soundCompleteTimeout
     * @type {timeoutVariable}
     * @default null
     * @protected
     * @since 0.4.0
     */
    this._soundCompleteTimeout = null;

    /**
     * NOTE this is only intended for use by very advanced users.
     * _sourceNodeNext is the audio source for the next loop, inserted in a look ahead approach to allow for smooth
     * looping. Connected to {{#crossLink "WebAudioSoundInstance/gainNode:property"}}{{/crossLink}}.
     * @property _sourceNodeNext
     * @type {AudioNode}
     * @default null
     * @protected
     * @since 0.4.1
     *
     */
    this._sourceNodeNext = null;

    /**
     * Time audio started playback, in seconds. Used to handle set position, get position, and resuming from paused.
     * @property _playbackStartTime
     * @type {Number}
     * @default 0
     * @protected
     * @since 0.4.0
     */
    this._playbackStartTime = 0;

    // Proxies, make removing listeners easier.
    this._endedHandler = createjs.proxy(this._handleSoundComplete, this);
  };
  var p = createjs.extend(WebAudioSoundInstance, createjs.AbstractSoundInstance);
  var s = WebAudioSoundInstance;

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


  /**
   * Note this is only intended for use by advanced users.
   * <br />Audio context used to create nodes.  This is and needs to be the same context used by {{#crossLink "WebAudioPlugin"}}{{/crossLink}}.
     * @property context
   * @type {AudioContext}
   * @static
   * @since 0.6.0
   */
  s.context = null;

  /**
   * Note this is only intended for use by advanced users.
   * <br /> Audio node from WebAudioPlugin that sequences to <code>context.destination</code>
   * @property destinationNode
   * @type {AudioNode}
   * @static
   * @since 0.6.0
   */
  s.destinationNode = null;

  /**
   * Value to set panning model to equal power for WebAudioSoundInstance.  Can be "equalpower" or 0 depending on browser implementation.
   * @property _panningModel
   * @type {Number / String}
   * @protected
   * @static
   * @since 0.6.0
   */
  s._panningModel = "equalpower";


// Public methods
  p.destroy = function() {
    this.AbstractSoundInstance_destroy();

    this.panNode.disconnect(0);
    this.panNode = null;
    this.gainNode.disconnect(0);
    this.gainNode = null;
  };

  p.toString = function () {
    return "[WebAudioSoundInstance]";
  };


// Private Methods
  p._updatePan = function() {
    this.panNode.setPosition(this._pan, 0, -0.5);
    // z need to be -0.5 otherwise the sound only plays in left, right, or center
  };

  p._removeLooping = function(value) {
    this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext);
  };

  p._addLooping = function(value) {
    if (this.playState != createjs.Sound.PLAY_SUCCEEDED) { return; }
    this._sourceNodeNext = this._createAndPlayAudioNode(this._playbackStartTime, 0);
  };

  p._setDurationFromSource = function () {
    this._duration = this.playbackResource.duration * 1000;
  };

  p._handleCleanUp = function () {
    if (this.sourceNode && this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this.sourceNode = this._cleanUpAudioNode(this.sourceNode);
      this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext);
    }

    if (this.gainNode.numberOfOutputs != 0) {this.gainNode.disconnect(0);}
    // OJR there appears to be a bug that this doesn't always work in webkit (Chrome and Safari). According to the documentation, this should work.

    clearTimeout(this._soundCompleteTimeout);

    this._playbackStartTime = 0;  // This is used by getPosition
  };

  /**
   * Turn off and disconnect an audioNode, then set reference to null to release it for garbage collection
   * @method _cleanUpAudioNode
   * @param audioNode
   * @return {audioNode}
   * @protected
   * @since 0.4.1
   */
  p._cleanUpAudioNode = function(audioNode) {
    if(audioNode) {
      audioNode.stop(0);
      audioNode.disconnect(0);
      audioNode = null;
    }
    return audioNode;
  };

  p._handleSoundReady = function (event) {
    this.gainNode.connect(s.destinationNode);  // this line can cause a memory leak.  Nodes need to be disconnected from the audioDestination or any sequence that leads to it.

    var dur = this._duration * 0.001;
    var pos = this._position * 0.001;
    if (pos > dur) {pos = dur;}
    this.sourceNode = this._createAndPlayAudioNode((s.context.currentTime - dur), pos);
    this._playbackStartTime = this.sourceNode.startTime - pos;

    this._soundCompleteTimeout = setTimeout(this._endedHandler, (dur - pos) * 1000);

    if(this._loop != 0) {
      this._sourceNodeNext = this._createAndPlayAudioNode(this._playbackStartTime, 0);
    }
  };

  /**
   * Creates an audio node using the current src and context, connects it to the gain node, and starts playback.
   * @method _createAndPlayAudioNode
   * @param {Number} startTime The time to add this to the web audio context, in seconds.
   * @param {Number} offset The amount of time into the src audio to start playback, in seconds.
   * @return {audioNode}
   * @protected
   * @since 0.4.1
   */
  p._createAndPlayAudioNode = function(startTime, offset) {
    var audioNode = s.context.createBufferSource();
    audioNode.buffer = this.playbackResource;
    audioNode.connect(this.panNode);
    var dur = this._duration * 0.001;
    audioNode.startTime = startTime + dur;
    audioNode.start(audioNode.startTime, offset+(this._startTime*0.001), dur - offset);
    return audioNode;
  };

  p._pause = function () {
    this._position = (s.context.currentTime - this._playbackStartTime) * 1000;  // * 1000 to give milliseconds, lets us restart at same point
    this.sourceNode = this._cleanUpAudioNode(this.sourceNode);
    this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext);

    if (this.gainNode.numberOfOutputs != 0) {this.gainNode.disconnect(0);}

    clearTimeout(this._soundCompleteTimeout);
  };

  p._resume = function () {
    this._handleSoundReady();
  };

  /*
  p._handleStop = function () {
    // web audio does not need to do anything extra
  };
  */

  p._updateVolume = function () {
    var newVolume = this._muted ? 0 : this._volume;
      if (newVolume != this.gainNode.gain.value) {
      this.gainNode.gain.value = newVolume;
      }
  };

  p._calculateCurrentPosition = function () {
    return ((s.context.currentTime - this._playbackStartTime) * 1000); // pos in seconds * 1000 to give milliseconds
  };

  p._updatePosition = function () {
    this.sourceNode = this._cleanUpAudioNode(this.sourceNode);
    this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext);
    clearTimeout(this._soundCompleteTimeout);

    if (!this._paused) {this._handleSoundReady();}
  };

  // OJR we are using a look ahead approach to ensure smooth looping.
  // We add _sourceNodeNext to the audio context so that it starts playing even if this callback is delayed.
  // This technique is described here:  http://www.html5rocks.com/en/tutorials/audio/scheduling/
  // NOTE the cost of this is that our audio loop may not always match the loop event timing precisely.
  p._handleLoop = function () {
    this._cleanUpAudioNode(this.sourceNode);
    this.sourceNode = this._sourceNodeNext;
    this._playbackStartTime = this.sourceNode.startTime;
    this._sourceNodeNext = this._createAndPlayAudioNode(this._playbackStartTime, 0);
    this._soundCompleteTimeout = setTimeout(this._endedHandler, this._duration);
  };

  p._updateDuration = function () {
    if(this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this._pause();
      this._resume();
    }
  };

  createjs.WebAudioSoundInstance = createjs.promote(WebAudioSoundInstance, "AbstractSoundInstance");
}());

//##############################################################################
// WebAudioPlugin.js
//##############################################################################

(function () {

  "use strict";

  /**
   * Play sounds using Web Audio in the browser. The WebAudioPlugin is currently the default plugin, and will be used
   * anywhere that it is supported. To change plugin priority, check out the Sound API
   * {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} method.

   * <h4>Known Browser and OS issues for Web Audio</h4>
   * <b>Firefox 25</b>
   * <ul><li>mp3 audio files do not load properly on all windows machines, reported
   * <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=929969" target="_blank">here</a>. </br>
   * For this reason it is recommended to pass another FF supported type (ie ogg) first until this bug is resolved, if possible.</li></ul>
   * <br />
   * <b>Webkit (Chrome and Safari)</b>
   * <ul><li>AudioNode.disconnect does not always seem to work.  This can cause the file size to grow over time if you
   * are playing a lot of audio files.</li></ul>
   * <br />
   * <b>iOS 6 limitations</b>
   *  <ul><li>Sound is initially muted and will only unmute through play being called inside a user initiated event (touch/click).</li>
   *  <li>A bug exists that will distort uncached audio when a video element is present in the DOM.  You can avoid this bug
   *  by ensuring the audio and video audio share the same sampleRate.</li>
   * </ul>
   * @class WebAudioPlugin
   * @extends AbstractPlugin
   * @constructor
   * @since 0.4.0
   */
  function WebAudioPlugin() {
    this.AbstractPlugin_constructor();


// Private Properties
    /**
     * Value to set panning model to equal power for WebAudioSoundInstance.  Can be "equalpower" or 0 depending on browser implementation.
     * @property _panningModel
     * @type {Number / String}
     * @protected
     */
    this._panningModel = s._panningModel;;

    /**
     * The web audio context, which WebAudio uses to play audio. All nodes that interact with the WebAudioPlugin
     * need to be created within this context.
     * @property context
     * @type {AudioContext}
     */
    this.context = s.context;

    /**
     * A DynamicsCompressorNode, which is used to improve sound quality and prevent audio distortion.
     * It is connected to <code>context.destination</code>.
     *
     * Can be accessed by advanced users through createjs.Sound.activePlugin.dynamicsCompressorNode.
     * @property dynamicsCompressorNode
     * @type {AudioNode}
     */
    this.dynamicsCompressorNode = this.context.createDynamicsCompressor();
    this.dynamicsCompressorNode.connect(this.context.destination);

    /**
     * A GainNode for controlling master volume. It is connected to {{#crossLink "WebAudioPlugin/dynamicsCompressorNode:property"}}{{/crossLink}}.
     *
     * Can be accessed by advanced users through createjs.Sound.activePlugin.gainNode.
     * @property gainNode
     * @type {AudioGainNode}
     */
    this.gainNode = this.context.createGain();
    this.gainNode.connect(this.dynamicsCompressorNode);
    createjs.WebAudioSoundInstance.destinationNode = this.gainNode;

    this._capabilities = s._capabilities;

    this._loaderClass = createjs.WebAudioLoader;
    this._soundInstanceClass = createjs.WebAudioSoundInstance;

    this._addPropsToClasses();
  }
  var p = createjs.extend(WebAudioPlugin, createjs.AbstractPlugin);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// Static Properties
  var s = WebAudioPlugin;
  /**
   * The capabilities of the plugin. This is generated via the {{#crossLink "WebAudioPlugin/_generateCapabilities:method"}}{{/crossLink}}
   * method and is used internally.
   * @property _capabilities
   * @type {Object}
   * @default null
   * @protected
   * @static
   */
  s._capabilities = null;

  /**
   * Value to set panning model to equal power for WebAudioSoundInstance.  Can be "equalpower" or 0 depending on browser implementation.
   * @property _panningModel
   * @type {Number / String}
   * @protected
   * @static
   */
  s._panningModel = "equalpower";

  /**
   * The web audio context, which WebAudio uses to play audio. All nodes that interact with the WebAudioPlugin
   * need to be created within this context.
   *
   * Advanced users can set this to an existing context, but <b>must</b> do so before they call
   * {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} or {{#crossLink "Sound/initializeDefaultPlugins"}}{{/crossLink}}.
   *
   * @property context
   * @type {AudioContext}
   * @static
   */
  s.context = null;


// Static Public Methods
  /**
   * Determine if the plugin can be used in the current browser/OS.
   * @method isSupported
   * @return {Boolean} If the plugin can be initialized.
   * @static
   */
  s.isSupported = function () {
    return false;
    // check if this is some kind of mobile device, Web Audio works with local protocol under PhoneGap and it is unlikely someone is trying to run a local file
    var isMobilePhoneGap = createjs.BrowserDetect.isIOS || createjs.BrowserDetect.isAndroid || createjs.BrowserDetect.isBlackberry;
    // OJR isMobile may be redundant with _isFileXHRSupported available.  Consider removing.
    // if (location.protocol == "file:" && !isMobilePhoneGap && !this._isFileXHRSupported()) { return false; }  // Web Audio requires XHR, which is not usually available locally
    s._generateCapabilities();
    if (s.context == null) {return false;}
    return true;
  };

  /**
   * Plays an empty sound in the web audio context.  This is used to enable web audio on iOS devices, as they
   * require the first sound to be played inside of a user initiated event (touch/click).  This is called when
   * {{#crossLink "WebAudioPlugin"}}{{/crossLink}} is initialized (by Sound {{#crossLink "Sound/initializeDefaultPlugins"}}{{/crossLink}}
   * for example).
   *
   * <h4>Example</h4>
   *
   *     function handleTouch(event) {
   *         createjs.WebAudioPlugin.playEmptySound();
   *     }
   *
   * @method playEmptySound
   * @static
   * @since 0.4.1
   */
  s.playEmptySound = function() {
    if (s.context == null) {return;}
    var source = s.context.createBufferSource();
    source.buffer = s.context.createBuffer(1, 1, 22050);
    source.connect(s.context.destination);
    source.start(0, 0, 0);
  };


// Static Private Methods
  /**
   * Determine if XHR is supported, which is necessary for web audio.
   * @method _isFileXHRSupported
   * @return {Boolean} If XHR is supported.
   * @since 0.4.2
   * @protected
   * @static
   */
  s._isFileXHRSupported = function() {
    // it's much easier to detect when something goes wrong, so let's start optimistically
    var supported = true;

    var xhr = new XMLHttpRequest();
    try {
      xhr.open("GET", "WebAudioPluginTest.fail", false); // loading non-existant file triggers 404 only if it could load (synchronous call)
    } catch (error) {
      // catch errors in cases where the onerror is passed by
      supported = false;
      return supported;
    }
    xhr.onerror = function() { supported = false; }; // cause irrelevant
    // with security turned off, we can get empty success results, which is actually a failed read (status code 0?)
    xhr.onload = function() { supported = this.status == 404 || (this.status == 200 || (this.status == 0 && this.response != "")); };
    try {
      xhr.send();
    } catch (error) {
      // catch errors in cases where the onerror is passed by
      supported = false;
    }

    return supported;
  };

  /**
   * Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/getCapabilities"}}{{/crossLink}}
   * method for an overview of plugin capabilities.
   * @method _generateCapabilities
   * @static
   * @protected
   */
  s._generateCapabilities = function () {
    if (s._capabilities != null) {return;}
    // Web Audio can be in any formats supported by the audio element, from http://www.w3.org/TR/webaudio/#AudioContext-section
    var t = document.createElement("audio");
    if (t.canPlayType == null) {return null;}

    if (s.context == null) {
      if (window.AudioContext) {
        s.context = new AudioContext();
      } else if (window.webkitAudioContext) {
        s.context = new webkitAudioContext();
      } else {
        return null;
      }
    }

    s._compatibilitySetUp();

    // playing this inside of a touch event will enable audio on iOS, which starts muted
    s.playEmptySound();

    s._capabilities = {
      panning:true,
      volume:true,
      tracks:-1
    };

    // determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS
    var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS;
    var extensionMap = createjs.Sound.EXTENSION_MAP;
    for (var i = 0, l = supportedExtensions.length; i < l; i++) {
      var ext = supportedExtensions[i];
      var playType = extensionMap[ext] || ext;
      s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != "");
    }  // OJR another way to do this might be canPlayType:"m4a", codex: mp4

    // 0=no output, 1=mono, 2=stereo, 4=surround, 6=5.1 surround.
    // See http://www.w3.org/TR/webaudio/#AudioChannelSplitter for more details on channels.
    if (s.context.destination.numberOfChannels < 2) {
      s._capabilities.panning = false;
    }
  };

  /**
   * Set up compatibility if only deprecated web audio calls are supported.
   * See http://www.w3.org/TR/webaudio/#DeprecationNotes
   * Needed so we can support new browsers that don't support deprecated calls (Firefox) as well as old browsers that
   * don't support new calls.
   *
   * @method _compatibilitySetUp
   * @static
   * @protected
   * @since 0.4.2
   */
  s._compatibilitySetUp = function() {
    s._panningModel = "equalpower";
    //assume that if one new call is supported, they all are
    if (s.context.createGain) { return; }

    // simple name change, functionality the same
    s.context.createGain = s.context.createGainNode;

    // source node, add to prototype
    var audioNode = s.context.createBufferSource();
    audioNode.__proto__.start = audioNode.__proto__.noteGrainOn;  // note that noteGrainOn requires all 3 parameters
    audioNode.__proto__.stop = audioNode.__proto__.noteOff;

    // panningModel
    s._panningModel = 0;
  };


// Public Methods
  p.toString = function () {
    return "[WebAudioPlugin]";
  };


// Private Methods
  /**
   * Set up needed properties on supported classes WebAudioSoundInstance and WebAudioLoader.
   * @method _addPropsToClasses
   * @static
   * @protected
   * @since 0.6.0
   */
  p._addPropsToClasses = function() {
    var c = this._soundInstanceClass;
    c.context = this.context;
    c.destinationNode = this.gainNode;
    c._panningModel = this._panningModel;

    this._loaderClass.context = this.context;
  };


  /**
   * Set the gain value for master audio. Should not be called externally.
   * @method _updateVolume
   * @protected
   */
  p._updateVolume = function () {
    var newVolume = createjs.Sound._masterMute ? 0 : this._volume;
    if (newVolume != this.gainNode.gain.value) {
      this.gainNode.gain.value = newVolume;
    }
  };

  createjs.WebAudioPlugin = createjs.promote(WebAudioPlugin, "AbstractPlugin");
}());

//##############################################################################
// HTMLAudioTagPool.js
//##############################################################################

(function () {
  "use strict";

  /**
   * HTMLAudioTagPool is an object pool for HTMLAudio tag instances.
   * @class HTMLAudioTagPool
   * @param {String} src The source of the channel.
   * @protected
   */
  function HTMLAudioTagPool() {
      throw "HTMLAudioTagPool cannot be instantiated";
  }

  var s = HTMLAudioTagPool;

// Static Properties
  /**
   * A hash lookup of each base audio tag, indexed by the audio source.
   * @property _tags
   * @type {{}}
   * @static
   * @protected
   */
  s._tags = {};

  /**
   * An object pool for html audio tags
   * @property _tagPool
   * @type {TagPool}
   * @static
   * @protected
   */
  s._tagPool = new TagPool();

  /**
   * A hash lookup of if a base audio tag is available, indexed by the audio source
   * @property _tagsUsed
   * @type {{}}
   * @protected
   * @static
   */
  s._tagUsed = {};

// Static Methods
  /**
    * Get an audio tag with the given source.
    * @method get
    * @param {String} src The source file used by the audio tag.
    * @static
    */
   s.get = function (src) {
    var t = s._tags[src];
    if (t == null) {
      // create new base tag
      t = s._tags[src] = s._tagPool.get();
      t.src = src;
    } else {
      // get base or pool
      if (s._tagUsed[src]) {
        t = s._tagPool.get();
        t.src = src;
      } else {
        s._tagUsed[src] = true;
      }
    }
    return t;
   };

   /**
    * Return an audio tag to the pool.
    * @method set
    * @param {String} src The source file used by the audio tag.
    * @param {HTMLElement} tag Audio tag to set.
    * @static
    */
   s.set = function (src, tag) {
     // check if this is base, if yes set boolean if not return to pool
     if(tag == s._tags[src]) {
       s._tagUsed[src] = false;
     } else {
       s._tagPool.set(tag);
     }
   };

  /**
   * Delete stored tag reference and return them to pool. Note that if the tag reference does not exist, this will fail.
   * @method remove
   * @param {String} src The source for the tag
   * @return {Boolean} If the TagPool was deleted.
   * @static
   */
  s.remove = function (src) {
    var tag = s._tags[src];
    if (tag == null) {return false;}
    s._tagPool.set(tag);
    delete(s._tags[src]);
    delete(s._tagUsed[src]);
    return true;
  };

  /**
   * Gets the duration of the src audio in milliseconds
   * @method getDuration
   * @param {String} src The source file used by the audio tag.
   * @return {Number} Duration of src in milliseconds
   * @static
   */
  s.getDuration= function (src) {
    var t = s._tags[src];
    if (t == null) {return 0;}
    return t.duration * 1000;
  };

  createjs.HTMLAudioTagPool = HTMLAudioTagPool;


// ************************************************************************************************************
  /**
   * The TagPool is an object pool for HTMLAudio tag instances.
   * #class TagPool
   * @param {String} src The source of the channel.
   * @protected
   */
  function TagPool(src) {

// Public Properties
    /**
     * A list of all available tags in the pool.
     * #property tags
     * @type {Array}
     * @protected
     */
    this._tags = [];
  };

  var p = TagPool.prototype;
  p.constructor = TagPool;


// Public Methods
  /**
   * Get an HTMLAudioElement for immediate playback. This takes it out of the pool.
   * #method get
   * @return {HTMLAudioElement} An HTML audio tag.
   */
  p.get = function () {
    var tag;
    if (this._tags.length == 0) {
      tag = this._createTag();
    } else {
      tag = this._tags.pop();
    }
    if (tag.parentNode == null) {document.body.appendChild(tag);}
    return tag;
  };

  /**
   * Put an HTMLAudioElement back in the pool for use.
   * #method set
   * @param {HTMLAudioElement} tag HTML audio tag
   */
  p.set = function (tag) {
    // OJR this first step seems unnecessary
    var index = createjs.indexOf(this._tags, tag);
    if (index == -1) {
      this._tags.src = null;
      this._tags.push(tag);
    }
  };

  p.toString = function () {
    return "[TagPool]";
  };


// Private Methods
  /**
   * Create an HTML audio tag.
   * #method _createTag
   * @param {String} src The source file to set for the audio tag.
   * @return {HTMLElement} Returns an HTML audio tag.
   * @protected
   */
  p._createTag = function () {
    var tag = document.createElement("audio");
    tag.autoplay = false;
    tag.preload = "none";
    //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works.
    return tag;
  };

}());

//##############################################################################
// HTMLAudioSoundInstance.js
//##############################################################################

(function () {
  "use strict";

  /**
   * HTMLAudioSoundInstance extends the base api of {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} and is used by
   * {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}.
   *
   * @param {String} src The path to and file name of the sound.
   * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds.
   * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds.
   * @param {Object} playbackResource Any resource needed by plugin to support audio playback.
   * @class HTMLAudioSoundInstance
   * @extends AbstractSoundInstance
   * @constructor
   */
  function HTMLAudioSoundInstance(src, startTime, duration, playbackResource) {
    this.AbstractSoundInstance_constructor(src, startTime, duration, playbackResource);


// Private Properties
    this._audioSpriteStopTime = null;
    this._delayTimeoutId = null;

    // Proxies, make removing listeners easier.
    this._endedHandler = createjs.proxy(this._handleSoundComplete, this);
    this._readyHandler = createjs.proxy(this._handleTagReady, this);
    this._stalledHandler = createjs.proxy(this._playFailed, this);
    this._audioSpriteEndHandler = createjs.proxy(this._handleAudioSpriteLoop, this);
    this._loopHandler = createjs.proxy(this._handleSoundComplete, this);

    if (duration) {
      this._audioSpriteStopTime = (startTime + duration) * 0.001;
    } else {
      this._duration = createjs.HTMLAudioTagPool.getDuration(this.src);
    }
  }
  var p = createjs.extend(HTMLAudioSoundInstance, createjs.AbstractSoundInstance);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// Public Methods
  /**
   * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master volume.
   * undoc'd because it is not meant to be used outside of Sound
   * #method setMasterVolume
   * @param value
   */
  p.setMasterVolume = function (value) {
    this._updateVolume();
  };

  /**
   * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master mute.
   * undoc'd because it is not meant to be used outside of Sound
   * #method setMasterMute
   * @param value
   */
  p.setMasterMute = function (isMuted) {
    this._updateVolume();
  };

  p.toString = function () {
    return "[HTMLAudioSoundInstance]";
  };

//Private Methods
  p._removeLooping = function() {
    if(this._playbackResource == null) {return;}
    this._playbackResource.loop = false;
    this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
  };

  p._addLooping = function() {
    if(this._playbackResource == null  || this._audioSpriteStopTime) {return;}
    this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
    this._playbackResource.loop = true;
  };

  p._handleCleanUp = function () {
    var tag = this._playbackResource;
    if (tag != null) {
      tag.pause();
      tag.loop = false;
      tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false);
      tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false);
      tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false);
      tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
      tag.removeEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false);

      try {
        tag.currentTime = this._startTime;
      } catch (e) {
      } // Reset Position
      createjs.HTMLAudioTagPool.set(this.src, tag);
      this._playbackResource = null;
    }
  };

  p._beginPlaying = function (playProps) {
    this._playbackResource = createjs.HTMLAudioTagPool.get(this.src);
    return this.AbstractSoundInstance__beginPlaying(playProps);
  };

  p._handleSoundReady = function (event) {
    if (this._playbackResource.readyState !== 4) {
      var tag = this._playbackResource;
      tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false);
      tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false);
      tag.preload = "auto"; // This is necessary for Firefox, as it won't ever "load" until this is set.
      tag.load();
      return;
    }

    this._updateVolume();
    this._playbackResource.currentTime = (this._startTime + this._position) * 0.001;
    if (this._audioSpriteStopTime) {
      this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false);
    } else {
      this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false);
      if(this._loop != 0) {
        this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
        this._playbackResource.loop = true;
      }
    }

    this._playbackResource.play();
  };

  /**
   * Used to handle when a tag is not ready for immediate playback when it is returned from the HTMLAudioTagPool.
   * @method _handleTagReady
   * @param event
   * @protected
   */
  p._handleTagReady = function (event) {
    this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false);
    this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false);

    this._handleSoundReady();
  };

  p._pause = function () {
    this._playbackResource.pause();
  };

  p._resume = function () {
    this._playbackResource.play();
  };

  p._updateVolume = function () {
    if (this._playbackResource != null) {
      var newVolume = (this._muted || createjs.Sound._masterMute) ? 0 : this._volume * createjs.Sound._masterVolume;
      if (newVolume != this._playbackResource.volume) {this._playbackResource.volume = newVolume;}
    }
  };

  p._calculateCurrentPosition = function() {
    return (this._playbackResource.currentTime * 1000) - this._startTime;
  };

  p._updatePosition = function() {
    this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
    this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._handleSetPositionSeek, false);
    try {
      this._playbackResource.currentTime = (this._position + this._startTime) * 0.001;
    } catch (error) { // Out of range
      this._handleSetPositionSeek(null);
    }
  };

  /**
   * Used to enable setting position, as we need to wait for that seek to be done before we add back our loop handling seek listener
   * @method _handleSetPositionSeek
   * @param event
   * @protected
   */
  p._handleSetPositionSeek = function(event) {
    if (this._playbackResource == null) { return; }
    this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._handleSetPositionSeek, false);
    this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
  };

  /**
   * Timer used to loop audio sprites.
   * NOTE because of the inaccuracies in the timeupdate event (15 - 250ms) and in setting the tag to the desired timed
   * (up to 300ms), it is strongly recommended not to loop audio sprites with HTML Audio if smooth looping is desired
   *
   * @method _handleAudioSpriteLoop
   * @param event
   * @private
   */
  p._handleAudioSpriteLoop = function (event) {
    if(this._playbackResource.currentTime <= this._audioSpriteStopTime) {return;}
    this._playbackResource.pause();
    if(this._loop == 0) {
      this._handleSoundComplete(null);
    } else {
      this._position = 0;
      this._loop--;
      this._playbackResource.currentTime = this._startTime * 0.001;
      if(!this._paused) {this._playbackResource.play();}
      this._sendEvent("loop");
    }
  };

  // NOTE with this approach audio will loop as reliably as the browser allows
  // but we could end up sending the loop event after next loop playback begins
  p._handleLoop = function (event) {
    if(this._loop == 0) {
      this._playbackResource.loop = false;
      this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false);
    }
  };

  p._updateStartTime = function () {
    this._audioSpriteStopTime = (this._startTime + this._duration) * 0.001;

    if(this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false);
      this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false);
    }
  };

  p._updateDuration = function () {
    this._audioSpriteStopTime = (this._startTime + this._duration) * 0.001;

    if(this.playState == createjs.Sound.PLAY_SUCCEEDED) {
      this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false);
      this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false);
    }
  };

  /*  This should never change
  p._setDurationFromSource = function () {
    this._duration = createjs.HTMLAudioTagPool.getDuration(this.src);
  };
  */

  createjs.HTMLAudioSoundInstance = createjs.promote(HTMLAudioSoundInstance, "AbstractSoundInstance");
}());

//##############################################################################
// HTMLAudioPlugin.js
//##############################################################################

(function () {

  "use strict";

  /**
   * Play sounds using HTML &lt;audio&gt; tags in the browser. This plugin is the second priority plugin installed
   * by default, after the {{#crossLink "WebAudioPlugin"}}{{/crossLink}}.  For older browsers that do not support html
   * audio, include and install the {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}.
   *
   * <h4>Known Browser and OS issues for HTML Audio</h4>
   * <b>All browsers</b><br />
   * Testing has shown in all browsers there is a limit to how many audio tag instances you are allowed.  If you exceed
   * this limit, you can expect to see unpredictable results. Please use {{#crossLink "Sound.MAX_INSTANCES"}}{{/crossLink}} as
   * a guide to how many total audio tags you can safely use in all browsers.  This issue is primarily limited to IE9.
   *
     * <b>IE html limitations</b><br />
     * <ul><li>There is a delay in applying volume changes to tags that occurs once playback is started. So if you have
     * muted all sounds, they will all play during this delay until the mute applies internally. This happens regardless of
     * when or how you apply the volume change, as the tag seems to need to play to apply it.</li>
     * <li>MP3 encoding will not always work for audio tags if it's not default.  We've found default encoding with
     * 64kbps works.</li>
   * <li>Occasionally very short samples will get cut off.</li>
   * <li>There is a limit to how many audio tags you can load or play at once, which appears to be determined by
   * hardware and browser settings.  See {{#crossLink "HTMLAudioPlugin.MAX_INSTANCES"}}{{/crossLink}} for a safe estimate.
   * Note that audio sprites can be used as a solution to this issue.</li></ul>
   *
   * <b>Safari limitations</b><br />
   * <ul><li>Safari requires Quicktime to be installed for audio playback.</li></ul>
   *
   * <b>iOS 6 limitations</b><br />
   * <ul><li>can only have one &lt;audio&gt; tag</li>
   *    <li>can not preload or autoplay the audio</li>
   *    <li>can not cache the audio</li>
   *    <li>can not play the audio except inside a user initiated event.</li>
   *    <li>Note it is recommended to use {{#crossLink "WebAudioPlugin"}}{{/crossLink}} for iOS (6+)</li>
   *    <li>audio sprites can be used to mitigate some of these issues and are strongly recommended on iOS</li>
   * </ul>
   *
   * <b>Android Native Browser limitations</b><br />
   * <ul><li>We have no control over audio volume. Only the user can set volume on their device.</li>
   *      <li>We can only play audio inside a user event (touch/click).  This currently means you cannot loop sound or use a delay.</li></ul>
   * <b> Android Chrome 26.0.1410.58 specific limitations</b><br />
   * <ul> <li>Can only play 1 sound at a time.</li>
   *      <li>Sound is not cached.</li>
   *      <li>Sound can only be loaded in a user initiated touch/click event.</li>
   *      <li>There is a delay before a sound is played, presumably while the src is loaded.</li>
   * </ul>
   *
   * See {{#crossLink "Sound"}}{{/crossLink}} for general notes on known issues.
   *
   * @class HTMLAudioPlugin
   * @extends AbstractPlugin
   * @constructor
   */
  function HTMLAudioPlugin() {
    this.AbstractPlugin_constructor();


  // Public Properties
    /**
     * This is no longer needed as we are now using object pooling for tags.
     *
     * <b>NOTE this property only exists as a limitation of HTML audio.</b>
     * @property defaultNumChannels
     * @type {Number}
     * @default 2
     * @since 0.4.0
     * @deprecated
     */
    this.defaultNumChannels = 2;

    this._capabilities = s._capabilities;

    this._loaderClass = createjs.SoundLoader;
    this._soundInstanceClass = createjs.HTMLAudioSoundInstance;
  }

  var p = createjs.extend(HTMLAudioPlugin, createjs.AbstractPlugin);
  var s = HTMLAudioPlugin;

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.


// Static Properties
  /**
   * The maximum number of instances that can be loaded or played. This is a browser limitation, primarily limited to IE9.
   * The actual number varies from browser to browser (and is largely hardware dependant), but this is a safe estimate.
   * Audio sprites work around this limitation.
   * @property MAX_INSTANCES
   * @type {Number}
   * @default 30
   * @static
   */
  s.MAX_INSTANCES = 30;

  /**
   * Event constant for the "canPlayThrough" event for cleaner code.
   * @property _AUDIO_READY
   * @type {String}
   * @default canplaythrough
   * @static
   * @protected
   */
  s._AUDIO_READY = "canplaythrough";

  /**
   * Event constant for the "ended" event for cleaner code.
   * @property _AUDIO_ENDED
   * @type {String}
   * @default ended
   * @static
   * @protected
   */
  s._AUDIO_ENDED = "ended";

  /**
   * Event constant for the "seeked" event for cleaner code.  We utilize this event for maintaining loop events.
   * @property _AUDIO_SEEKED
   * @type {String}
   * @default seeked
   * @static
   * @protected
   */
  s._AUDIO_SEEKED = "seeked";

  /**
   * Event constant for the "stalled" event for cleaner code.
   * @property _AUDIO_STALLED
   * @type {String}
   * @default stalled
   * @static
   * @protected
   */
  s._AUDIO_STALLED = "stalled";

  /**
   * Event constant for the "timeupdate" event for cleaner code.  Utilized for looping audio sprites.
   * This event callsback ever 15 to 250ms and can be dropped by the browser for performance.
   * @property _TIME_UPDATE
   * @type {String}
   * @default timeupdate
   * @static
   * @protected
   */
  s._TIME_UPDATE = "timeupdate";

  /**
   * The capabilities of the plugin. This is generated via the {{#crossLink "HTMLAudioPlugin/_generateCapabilities"}}{{/crossLink}}
   * method. Please see the Sound {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} method for an overview of all
   * of the available properties.
   * @property _capabilities
   * @type {Object}
   * @protected
   * @static
   */
  s._capabilities = null;


// Static Methods
  /**
   * Determine if the plugin can be used in the current browser/OS. Note that HTML audio is available in most modern
   * browsers, but is disabled in iOS because of its limitations.
   * @method isSupported
   * @return {Boolean} If the plugin can be initialized.
   * @static
   */
  s.isSupported = function () {
    s._generateCapabilities();
    return (s._capabilities != null);
  };

  /**
   * Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/getCapabilities"}}{{/crossLink}}
   * method for an overview of plugin capabilities.
   * @method _generateCapabilities
   * @static
   * @protected
   */
  s._generateCapabilities = function () {
    if (s._capabilities != null) {return;}
    var t = document.createElement("audio");
    if (t.canPlayType == null) {return null;}

    s._capabilities = {
      panning:false,
      volume:true,
      tracks:-1
    };

    // determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS
    var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS;
    var extensionMap = createjs.Sound.EXTENSION_MAP;
    for (var i = 0, l = supportedExtensions.length; i < l; i++) {
      var ext = supportedExtensions[i];
      var playType = extensionMap[ext] || ext;
      s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != "");
    }  // OJR another way to do this might be canPlayType:"m4a", codex: mp4
  };


// public methods
  p.register = function (loadItem) {
    var tag = createjs.HTMLAudioTagPool.get(loadItem.src);
    var loader = this.AbstractPlugin_register(loadItem);
    loader.setTag(tag);

    return loader;
  };

  p.removeSound = function (src) {
    this.AbstractPlugin_removeSound(src);
    createjs.HTMLAudioTagPool.remove(src);
  };

  p.create = function (src, startTime, duration) {
    var si = this.AbstractPlugin_create(src, startTime, duration);
    si.setPlaybackResource(null);
    return si;
  };

  p.toString = function () {
    return "[HTMLAudioPlugin]";
  };

  // plugin does not support these
  p.setVolume = p.getVolume = p.setMute = null;


  createjs.HTMLAudioPlugin = createjs.promote(HTMLAudioPlugin, "AbstractPlugin");
}());

//##############################################################################
// Tween.js
//##############################################################################

// TODO: possibly add a END actionsMode (only runs actions that == position)?
// TODO: evaluate a way to decouple paused from tick registration.




(function() {
  "use strict";


// constructor
  /**
   * A Tween instance tweens properties for a single target. Instance methods can be chained for easy construction and sequencing:
   *
   * <h4>Example</h4>
   *
   *      target.alpha = 1;
   *      createjs.Tween.get(target)
   *           .wait(500)
   *           .to({alpha:0, visible:false}, 1000)
   *           .call(handleComplete);
   *      function handleComplete() {
   *        //Tween complete
   *      }
   *
   * Multiple tweens can point to the same instance, however if they affect the same properties there could be unexpected
   * behaviour. To stop all tweens on an object, use {{#crossLink "Tween/removeTweens"}}{{/crossLink}} or pass `override:true`
   * in the props argument.
   *
   *      createjs.Tween.get(target, {override:true}).to({x:100});
   *
   * Subscribe to the {{#crossLink "Tween/change:event"}}{{/crossLink}} event to get notified when a property of the
   * target is changed.
   *
   *      createjs.Tween.get(target, {override:true}).to({x:100}).addEventListener("change", handleChange);
   *      function handleChange(event) {
   *          // The tween changed.
   *      }
   *
   * See the Tween {{#crossLink "Tween/get"}}{{/crossLink}} method for additional param documentation.
   * @class Tween
   * @param {Object} target The target object that will have its properties tweened.
   * @param {Object} [props] The configuration properties to apply to this tween instance (ex. `{loop:true, paused:true}`.
   * All properties default to false. Supported props are:<UL>
   *    <LI> loop: sets the loop property on this tween.</LI>
   *    <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI>
   *    <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on this tween.</LI>
   *    <LI> override: if true, `Tween.removeTweens(target)` will be called to remove any other tweens with the same target.
   *    <LI> paused: indicates whether to start the tween paused.</LI>
   *    <LI> position: indicates the initial position for this tween.</LI>
   *    <LI> onChange: specifies a listener for the "change" event.</LI>
   * </UL>
   * @param {Object} [pluginData] An object containing data for use by installed plugins. See individual
   * plugins' documentation for details.
   * @extends EventDispatcher
   * @constructor
   */
  function Tween(target, props, pluginData) {

  // public properties:
    /**
     * Causes this tween to continue playing when a global pause is active. For example, if TweenJS is using {{#crossLink "Ticker"}}{{/crossLink}},
     * then setting this to true (the default) will cause this tween to be paused when <code>Ticker.setPaused(true)</code>
     * is called. See the Tween {{#crossLink "Tween/tick"}}{{/crossLink}} method for more info. Can be set via the props
     * parameter.
     * @property ignoreGlobalPause
     * @type Boolean
     * @default false
     */
    this.ignoreGlobalPause = false;
  
    /**
     * If true, the tween will loop when it reaches the end. Can be set via the props param.
     * @property loop
     * @type {Boolean}
     * @default false
     */
    this.loop = false;
  
    /**
     * Specifies the total duration of this tween in milliseconds (or ticks if useTicks is true).
     * This value is automatically updated as you modify the tween. Changing it directly could result in unexpected
     * behaviour.
     * @property duration
     * @type {Number}
     * @default 0
     * @readonly
     */
    this.duration = 0;
  
    /**
     * Allows you to specify data that will be used by installed plugins. Each plugin uses this differently, but in general
     * you specify data by setting it to a property of pluginData with the same name as the plugin class.
     * @example
     *  myTween.pluginData.PluginClassName = data;
     * <br/>
     * Also, most plugins support a property to enable or disable them. This is typically the plugin class name followed by "_enabled".<br/>
     * @example
     *  myTween.pluginData.PluginClassName_enabled = false;<br/>
     * <br/>
     * Some plugins also store instance data in this object, usually in a property named _PluginClassName.
     * See the documentation for individual plugins for more details.
     * @property pluginData
     * @type {Object}
     */
    this.pluginData = pluginData || {};
  
    /**
     * The target of this tween. This is the object on which the tweened properties will be changed. Changing
     * this property after the tween is created will not have any effect.
     * @property target
     * @type {Object}
     * @readonly
     */
    this.target = target;
  
    /**
     * The current normalized position of the tween. This will always be a value between 0 and duration.
     * Changing this property directly will have no effect.
     * @property position
     * @type {Object}
     * @readonly
     */
    this.position = null;
  
    /**
     * Indicates the tween's current position is within a passive wait.
     * @property passive
     * @type {Boolean}
     * @default false
     * @readonly
     **/
    this.passive = false;
  
  // private properties:  
    /**
     * @property _paused
     * @type {Boolean}
     * @default false
     * @protected
     */
    this._paused = false;
  
    /**
     * @property _curQueueProps
     * @type {Object}
     * @protected
     */
    this._curQueueProps = {};
  
    /**
     * @property _initQueueProps
     * @type {Object}
     * @protected
     */
    this._initQueueProps = {};
  
    /**
     * @property _steps
     * @type {Array}
     * @protected
     */
    this._steps = [];
  
    /**
     * @property _actions
     * @type {Array}
     * @protected
     */
    this._actions = [];
  
    /**
     * Raw position.
     * @property _prevPosition
     * @type {Number}
     * @default 0
     * @protected
     */
    this._prevPosition = 0;
  
    /**
     * The position within the current step.
     * @property _stepPosition
     * @type {Number}
     * @default 0
     * @protected
     */
    this._stepPosition = 0; // this is needed by MovieClip.
  
    /**
     * Normalized position.
     * @property _prevPos
     * @type {Number}
     * @default -1
     * @protected
     */
    this._prevPos = -1;
  
    /**
     * @property _target
     * @type {Object}
     * @protected
     */
    this._target = target;
  
    /**
     * @property _useTicks
     * @type {Boolean}
     * @default false
     * @protected
     */
    this._useTicks = false;
  
    /**
     * @property _inited
     * @type {boolean}
     * @default false
     * @protected
     */
    this._inited = false;
    
    /**
     * Indicates whether the tween is currently registered with Tween.
     * @property _registered
     * @type {boolean}
     * @default false
     * @protected
     */
    this._registered = false;


    if (props) {
      this._useTicks = props.useTicks;
      this.ignoreGlobalPause = props.ignoreGlobalPause;
      this.loop = props.loop;
      props.onChange && this.addEventListener("change", props.onChange);
      if (props.override) { Tween.removeTweens(target); }
    }
    if (props&&props.paused) { this._paused=true; }
    else { createjs.Tween._register(this,true); }
    if (props&&props.position!=null) { this.setPosition(props.position, Tween.NONE); }

  };

  var p = createjs.extend(Tween, createjs.EventDispatcher);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
  

// static properties
  /**
   * Constant defining the none actionsMode for use with setPosition.
   * @property NONE
   * @type Number
   * @default 0
   * @static
   */
  Tween.NONE = 0;

  /**
   * Constant defining the loop actionsMode for use with setPosition.
   * @property LOOP
   * @type Number
   * @default 1
   * @static
   */
  Tween.LOOP = 1;

  /**
   * Constant defining the reverse actionsMode for use with setPosition.
   * @property REVERSE
   * @type Number
   * @default 2
   * @static
   */
  Tween.REVERSE = 2;

  /**
   * Constant returned by plugins to tell the tween not to use default assignment.
   * @property IGNORE
   * @type Object
   * @static
   */
  Tween.IGNORE = {};

  /**
   * @property _listeners
   * @type Array[Tween]
   * @static
   * @protected
   */
  Tween._tweens = [];

  /**
   * @property _plugins
   * @type Object
   * @static
   * @protected
   */
  Tween._plugins = {};


// static methods 
  /**
   * Returns a new tween instance. This is functionally identical to using "new Tween(...)", but looks cleaner
   * with the chained syntax of TweenJS.
   * <h4>Example</h4>
   *
   *    var tween = createjs.Tween.get(target);
   *
   * @method get
   * @param {Object} target The target object that will have its properties tweened.
   * @param {Object} [props] The configuration properties to apply to this tween instance (ex. `{loop:true, paused:true}`).
   * All properties default to `false`. Supported props are:
   * <UL>
   *    <LI> loop: sets the loop property on this tween.</LI>
   *    <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI>
   *    <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on
   *    this tween.</LI>
   *    <LI> override: if true, `createjs.Tween.removeTweens(target)` will be called to remove any other tweens with
   *    the same target.
   *    <LI> paused: indicates whether to start the tween paused.</LI>
   *    <LI> position: indicates the initial position for this tween.</LI>
   *    <LI> onChange: specifies a listener for the {{#crossLink "Tween/change:event"}}{{/crossLink}} event.</LI>
   * </UL>
   * @param {Object} [pluginData] An object containing data for use by installed plugins. See individual plugins'
   * documentation for details.
   * @param {Boolean} [override=false] If true, any previous tweens on the same target will be removed. This is the
   * same as calling `Tween.removeTweens(target)`.
   * @return {Tween} A reference to the created tween. Additional chained tweens, method calls, or callbacks can be
   * applied to the returned tween instance.
   * @static
   */
  Tween.get = function(target, props, pluginData, override) {
    if (override) { Tween.removeTweens(target); }
    return new Tween(target, props, pluginData);
  };

  /**
   * Advances all tweens. This typically uses the {{#crossLink "Ticker"}}{{/crossLink}} class, but you can call it
   * manually if you prefer to use your own "heartbeat" implementation.
   * @method tick
   * @param {Number} delta The change in time in milliseconds since the last tick. Required unless all tweens have
   * `useTicks` set to true.
   * @param {Boolean} paused Indicates whether a global pause is in effect. Tweens with {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}}
   * will ignore this, but all others will pause if this is `true`.
   * @static
   */
  Tween.tick = function(delta, paused) {
    var tweens = Tween._tweens.slice(); // to avoid race conditions.
    for (var i=tweens.length-1; i>=0; i--) {
      var tween = tweens[i];
      if ((paused && !tween.ignoreGlobalPause) || tween._paused) { continue; }
      tween.tick(tween._useTicks?1:delta);
    }
  };

  /**
   * Handle events that result from Tween being used as an event handler. This is included to allow Tween to handle
   * {{#crossLink "Ticker/tick:event"}}{{/crossLink}} events from the createjs {{#crossLink "Ticker"}}{{/crossLink}}.
   * No other events are handled in Tween.
   * @method handleEvent
   * @param {Object} event An event object passed in by the {{#crossLink "EventDispatcher"}}{{/crossLink}}. Will
   * usually be of type "tick".
   * @private
   * @static
   * @since 0.4.2
   */
  Tween.handleEvent = function(event) {
    if (event.type == "tick") {
      this.tick(event.delta, event.paused);
    }
  };

  /**
   * Removes all existing tweens for a target. This is called automatically by new tweens if the `override`
   * property is `true`.
   * @method removeTweens
   * @param {Object} target The target object to remove existing tweens from.
   * @static
   */
  Tween.removeTweens = function(target) {
    if (!target.tweenjs_count) { return; }
    var tweens = Tween._tweens;
    for (var i=tweens.length-1; i>=0; i--) {
      var tween = tweens[i];
      if (tween._target == target) {
        tween._paused = true;
        tweens.splice(i, 1);
      }
    }
    target.tweenjs_count = 0;
  };

  /**
   * Stop and remove all existing tweens.
   * @method removeAllTweens
   * @static
   * @since 0.4.1
   */
  Tween.removeAllTweens = function() {
    var tweens = Tween._tweens;
    for (var i= 0, l=tweens.length; i<l; i++) {
      var tween = tweens[i];
      tween._paused = true;
      tween.target&&(tween.target.tweenjs_count = 0);
    }
    tweens.length = 0;
  };

  /**
   * Indicates whether there are any active tweens (and how many) on the target object (if specified) or in general.
   * @method hasActiveTweens
   * @param {Object} [target] The target to check for active tweens. If not specified, the return value will indicate
   * if there are any active tweens on any target.
   * @return {Boolean} If there are active tweens.
   * @static
   */
  Tween.hasActiveTweens = function(target) {
    if (target) { return target.tweenjs_count != null && !!target.tweenjs_count; }
    return Tween._tweens && !!Tween._tweens.length;
  };

  /**
   * Installs a plugin, which can modify how certain properties are handled when tweened. See the {{#crossLink "CSSPlugin"}}{{/crossLink}}
   * for an example of how to write TweenJS plugins.
   * @method installPlugin
   * @static
   * @param {Object} plugin The plugin class to install
   * @param {Array} properties An array of properties that the plugin will handle.
   */
  Tween.installPlugin = function(plugin, properties) {
    var priority = plugin.priority;
    if (priority == null) { plugin.priority = priority = 0; }
    for (var i=0,l=properties.length,p=Tween._plugins;i<l;i++) {
      var n = properties[i];
      if (!p[n]) { p[n] = [plugin]; }
      else {
        var arr = p[n];
        for (var j=0,jl=arr.length;j<jl;j++) {
          if (priority < arr[j].priority) { break; }
        }
        p[n].splice(j,0,plugin);
      }
    }
  };

  /**
   * Registers or unregisters a tween with the ticking system.
   * @method _register
   * @param {Tween} tween The tween instance to register or unregister.
   * @param {Boolean} value If `true`, the tween is registered. If `false` the tween is unregistered.
   * @static
   * @protected
   */
  Tween._register = function(tween, value) {
    var target = tween._target;
    var tweens = Tween._tweens;
    if (value && !tween._registered) {
      // TODO: this approach might fail if a dev is using sealed objects in ES5
      if (target) { target.tweenjs_count = target.tweenjs_count ? target.tweenjs_count+1 : 1; }
      tweens.push(tween);
      if (!Tween._inited && createjs.Ticker) { createjs.Ticker.addEventListener("tick", Tween); Tween._inited = true; }
    } else if (!value && tween._registered) {
      if (target) { target.tweenjs_count--; }
      var i = tweens.length;
      while (i--) {
        if (tweens[i] == tween) {
          tweens.splice(i, 1);
          break;
        }
      }
    }
    tween._registered = value;
  };


// events:
  /**
   * Called whenever the tween's position changes.
   * @event change
   * @since 0.4.0
   **/
  

// public methods:
  /**
   * Queues a wait (essentially an empty tween).
   * <h4>Example</h4>
   *
   *    //This tween will wait 1s before alpha is faded to 0.
   *    createjs.Tween.get(target).wait(1000).to({alpha:0}, 1000);
   *
   * @method wait
   * @param {Number} duration The duration of the wait in milliseconds (or in ticks if `useTicks` is true).
   * @param {Boolean} [passive] Tween properties will not be updated during a passive wait. This
   * is mostly useful for use with {{#crossLink "Timeline"}}{{/crossLink}} instances that contain multiple tweens
   * affecting the same target at different times.
   * @return {Tween} This tween instance (for chaining calls).
   **/
  p.wait = function(duration, passive) {
    if (duration == null || duration <= 0) { return this; }
    var o = this._cloneProps(this._curQueueProps);
    return this._addStep({d:duration, p0:o, e:this._linearEase, p1:o, v:passive});
  };

  /**
   * Queues a tween from the current values to the target properties. Set duration to 0 to jump to these value.
   * Numeric properties will be tweened from their current value in the tween to the target value. Non-numeric
   * properties will be set at the end of the specified duration.
   * <h4>Example</h4>
   *
   *    createjs.Tween.get(target).to({alpha:0}, 1000);
   *
   * @method to
   * @param {Object} props An object specifying property target values for this tween (Ex. `{x:300}` would tween the x
   * property of the target to 300).
   * @param {Number} [duration=0] The duration of the wait in milliseconds (or in ticks if `useTicks` is true).
   * @param {Function} [ease="linear"] The easing function to use for this tween. See the {{#crossLink "Ease"}}{{/crossLink}}
   * class for a list of built-in ease functions.
   * @return {Tween} This tween instance (for chaining calls).
   */
  p.to = function(props, duration, ease) {
    if (isNaN(duration) || duration < 0) { duration = 0; }
    return this._addStep({d:duration||0, p0:this._cloneProps(this._curQueueProps), e:ease, p1:this._cloneProps(this._appendQueueProps(props))});
  };

  /**
   * Queues an action to call the specified function.
   * <h4>Example</h4>
   *
   *    //would call myFunction() after 1 second.
   *    myTween.wait(1000).call(myFunction);
   *
   * @method call
   * @param {Function} callback The function to call.
   * @param {Array} [params]. The parameters to call the function with. If this is omitted, then the function
   *      will be called with a single param pointing to this tween.
   * @param {Object} [scope]. The scope to call the function in. If omitted, it will be called in the target's
   *      scope.
   * @return {Tween} This tween instance (for chaining calls).
   */
  p.call = function(callback, params, scope) {
    return this._addAction({f:callback, p:params ? params : [this], o:scope ? scope : this._target});
  };

  // TODO: add clarification between this and a 0 duration .to:
  /**
   * Queues an action to set the specified props on the specified target. If target is null, it will use this tween's
   * target.
   * <h4>Example</h4>
   *
   *    myTween.wait(1000).set({visible:false},foo);
   *
   * @method set
   * @param {Object} props The properties to set (ex. `{visible:false}`).
   * @param {Object} [target] The target to set the properties on. If omitted, they will be set on the tween's target.
   * @return {Tween} This tween instance (for chaining calls).
   */
  p.set = function(props, target) {
    return this._addAction({f:this._set, o:this, p:[props, target ? target : this._target]});
  };

  /**
   * Queues an action to play (unpause) the specified tween. This enables you to sequence multiple tweens.
   * <h4>Example</h4>
   *
   *    myTween.to({x:100},500).play(otherTween);
   *
   * @method play
   * @param {Tween} tween The tween to play.
   * @return {Tween} This tween instance (for chaining calls).
   */
  p.play = function(tween) {
    if (!tween) { tween = this; }
    return this.call(tween.setPaused, [false], tween);
  };

  /**
   * Queues an action to pause the specified tween.
   * @method pause
   * @param {Tween} tween The tween to pause. If null, it pauses this tween.
   * @return {Tween} This tween instance (for chaining calls)
   */
  p.pause = function(tween) {
    if (!tween) { tween = this; }
    return this.call(tween.setPaused, [true], tween);
  };

  /**
   * Advances the tween to a specified position.
   * @method setPosition
   * @param {Number} value The position to seek to in milliseconds (or ticks if useTicks is true).
   * @param {Number} [actionsMode=1] Specifies how actions are handled (ie. call, set, play, pause):
   * <ul>
   *      <li>{{#crossLink "Tween/NONE:property"}}{{/crossLink}} (0) - run no actions.</li>
   *      <li>{{#crossLink "Tween/LOOP:property"}}{{/crossLink}} (1) - if new position is less than old, then run all
   *      actions between old and duration, then all actions between 0 and new.</li>
   *      <li>{{#crossLink "Tween/REVERSE:property"}}{{/crossLink}} (2) - if new position is less than old, run all
   *      actions between them in reverse.</li>
   * </ul>
   * @return {Boolean} Returns `true` if the tween is complete (ie. the full tween has run & {{#crossLink "Tween/loop:property"}}{{/crossLink}}
   * is `false`).
   */
  p.setPosition = function(value, actionsMode) {
    if (value < 0) { value = 0; }
    if (actionsMode == null) { actionsMode = 1; }

    // normalize position:
    var t = value;
    var end = false;
    if (t >= this.duration) {
      if (this.loop) { t = t%this.duration; }
      else {
        t = this.duration;
        end = true;
      }
    }
    if (t == this._prevPos) { return end; }


    var prevPos = this._prevPos;
    this.position = this._prevPos = t; // set this in advance in case an action modifies position.
    this._prevPosition = value;

    // handle tweens:
    if (this._target) {
      if (end) {
        // addresses problems with an ending zero length step.
        this._updateTargetProps(null,1);
      } else if (this._steps.length > 0) {
        // find our new tween index:
        for (var i=0, l=this._steps.length; i<l; i++) {
          if (this._steps[i].t > t) { break; }
        }
        var step = this._steps[i-1];
        this._updateTargetProps(step,(this._stepPosition = t-step.t)/step.d);
      }
    }

    // run actions:
    if (actionsMode != 0 && this._actions.length > 0) {
      if (this._useTicks) {
        // only run the actions we landed on.
        this._runActions(t,t);
      } else if (actionsMode == 1 && t<prevPos) {
        if (prevPos != this.duration) { this._runActions(prevPos, this.duration); }
        this._runActions(0, t, true);
      } else {
        this._runActions(prevPos, t);
      }
    }

    if (end) { this.setPaused(true); }

        this.dispatchEvent("change");
    return end;
  };

  /**
   * Advances this tween by the specified amount of time in milliseconds (or ticks if`useTicks` is `true`).
   * This is normally called automatically by the Tween engine (via {{#crossLink "Tween/tick"}}{{/crossLink}}), but is
   * exposed for advanced uses.
   * @method tick
   * @param {Number} delta The time to advance in milliseconds (or ticks if `useTicks` is `true`).
   */
  p.tick = function(delta) {
    if (this._paused) { return; }
    this.setPosition(this._prevPosition+delta);
  };

  /**
   * Pauses or plays this tween.
   * @method setPaused
   * @param {Boolean} [value=true] Indicates whether the tween should be paused (`true`) or played (`false`).
   * @return {Tween} This tween instance (for chaining calls)
   */
  p.setPaused = function(value) {
    if (this._paused === !!value) { return this; }
    this._paused = !!value;
    Tween._register(this, !value);
    return this;
  };

  // tiny api (primarily for tool output):
  p.w = p.wait;
  p.t = p.to;
  p.c = p.call;
  p.s = p.set;

  /**
   * Returns a string representation of this object.
   * @method toString
   * @return {String} a string representation of the instance.
   */
  p.toString = function() {
    return "[Tween]";
  };

  /**
   * @method clone
   * @protected
   */
  p.clone = function() {
    throw("Tween can not be cloned.")
  };

// private methods:
  /**
   * @method _updateTargetProps
   * @param {Object} step
   * @param {Number} ratio
   * @protected
   */
  p._updateTargetProps = function(step, ratio) {
    var p0,p1,v,v0,v1,arr;
    if (!step && ratio == 1) {
      // GDS: when does this run? Just at the very end? Shouldn't.
      this.passive = false;
      p0 = p1 = this._curQueueProps;
    } else {
      this.passive = !!step.v;
      if (this.passive) { return; } // don't update props.
      // apply ease to ratio.
      if (step.e) { ratio = step.e(ratio,0,1,1); }
      p0 = step.p0;
      p1 = step.p1;
    }

    for (var n in this._initQueueProps) {
      if ((v0 = p0[n]) == null) { p0[n] = v0 = this._initQueueProps[n]; }
      if ((v1 = p1[n]) == null) { p1[n] = v1 = v0; }
      if (v0 == v1 || ratio == 0 || ratio == 1 || (typeof(v0) != "number")) {
        // no interpolation - either at start, end, values don't change, or the value is non-numeric.
        v = ratio == 1 ? v1 : v0;
      } else {
        v = v0+(v1-v0)*ratio;
      }

      var ignore = false;
      if (arr = Tween._plugins[n]) {
        for (var i=0,l=arr.length;i<l;i++) {
          var v2 = arr[i].tween(this, n, v, p0, p1, ratio, !!step&&p0==p1, !step);
          if (v2 == Tween.IGNORE) { ignore = true; }
          else { v = v2; }
        }
      }
      if (!ignore) { this._target[n] = v; }
    }

  };

  /**
   * @method _runActions
   * @param {Number} startPos
   * @param {Number} endPos
   * @param {Boolean} includeStart
   * @protected
   */
  p._runActions = function(startPos, endPos, includeStart) {
    var sPos = startPos;
    var ePos = endPos;
    var i = -1;
    var j = this._actions.length;
    var k = 1;
    if (startPos > endPos) {
      // running backwards, flip everything:
      sPos = endPos;
      ePos = startPos;
      i = j;
      j = k = -1;
    }
    while ((i+=k) != j) {
      var action = this._actions[i];
      var pos = action.t;
      if (pos == ePos || (pos > sPos && pos < ePos) || (includeStart && pos == startPos) ) {
        action.f.apply(action.o, action.p);
      }
    }
  };

  /**
   * @method _appendQueueProps
   * @param {Object} o
   * @protected
   */
  p._appendQueueProps = function(o) {
    var arr,oldValue,i, l, injectProps;
    for (var n in o) {
      if (this._initQueueProps[n] === undefined) {
        oldValue = this._target[n];

        // init plugins:
        if (arr = Tween._plugins[n]) {
          for (i=0,l=arr.length;i<l;i++) {
            oldValue = arr[i].init(this, n, oldValue);
          }
        }
        this._initQueueProps[n] = this._curQueueProps[n] = (oldValue===undefined) ? null : oldValue;
      } else {
        oldValue = this._curQueueProps[n];
      }
    }

    for (var n in o) {
      oldValue = this._curQueueProps[n];
      if (arr = Tween._plugins[n]) {
        injectProps = injectProps||{};
        for (i=0, l=arr.length;i<l;i++) {
          // TODO: remove the check for .step in the next version. It's here for backwards compatibility.
          if (arr[i].step) { arr[i].step(this, n, oldValue, o[n], injectProps); }
        }
      }
      this._curQueueProps[n] = o[n];
    }
    if (injectProps) { this._appendQueueProps(injectProps); }
    return this._curQueueProps;
  };

  /**
   * @method _cloneProps
   * @param {Object} props
   * @protected
   */
  p._cloneProps = function(props) {
    var o = {};
    for (var n in props) {
      o[n] = props[n];
    }
    return o;
  };

  /**
   * @method _addStep
   * @param {Object} o
   * @protected
   */
  p._addStep = function(o) {
    if (o.d > 0) {
      this._steps.push(o);
      o.t = this.duration;
      this.duration += o.d;
    }
    return this;
  };

  /**
   * @method _addAction
   * @param {Object} o
   * @protected
   */
  p._addAction = function(o) {
    o.t = this.duration;
    this._actions.push(o);
    return this;
  };

  /**
   * @method _set
   * @param {Object} props
   * @param {Object} o
   * @protected
   */
  p._set = function(props, o) {
    for (var n in props) {
      o[n] = props[n];
    }
  };

  createjs.Tween = createjs.promote(Tween, "EventDispatcher");

}());

//##############################################################################
// Timeline.js
//##############################################################################

(function() {
  "use strict";
  

// constructor  
  /**
   * The Timeline class synchronizes multiple tweens and allows them to be controlled as a group. Please note that if a
   * timeline is looping, the tweens on it may appear to loop even if the "loop" property of the tween is false.
   * @class Timeline
   * @param {Array} tweens An array of Tweens to add to this timeline. See {{#crossLink "Timeline/addTween"}}{{/crossLink}}
   * for more info.
   * @param {Object} labels An object defining labels for using {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}}.
   * See {{#crossLink "Timeline/setLabels"}}{{/crossLink}}
   * for details.
   * @param {Object} props The configuration properties to apply to this tween instance (ex. `{loop:true}`). All properties
   * default to false. Supported props are:<UL>
   *    <LI> loop: sets the loop property on this tween.</LI>
   *    <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI>
   *    <LI> ignoreGlobalPause: sets the ignoreGlobalPause property on this tween.</LI>
   *    <LI> paused: indicates whether to start the tween paused.</LI>
   *    <LI> position: indicates the initial position for this timeline.</LI>
   *    <LI> onChange: specifies a listener to add for the {{#crossLink "Timeline/change:event"}}{{/crossLink}} event.</LI>
   * </UL>
   * @extends EventDispatcher
   * @constructor
   **/
  function Timeline(tweens, labels, props) {
    this.EventDispatcher_constructor();

  // public properties:
    /**
     * Causes this timeline to continue playing when a global pause is active.
     * @property ignoreGlobalPause
     * @type Boolean
     **/
    this.ignoreGlobalPause = false;

    /**
     * The total duration of this timeline in milliseconds (or ticks if `useTicks `is `true`). This value is usually
     * automatically updated as you modify the timeline. See {{#crossLink "Timeline/updateDuration"}}{{/crossLink}}
     * for more information.
     * @property duration
     * @type Number
     * @default 0
     * @readonly
     **/
    this.duration = 0;

    /**
     * If true, the timeline will loop when it reaches the end. Can be set via the props param.
     * @property loop
     * @type Boolean
     **/
    this.loop = false;

    /**
     * The current normalized position of the timeline. This will always be a value between 0 and
     * {{#crossLink "Timeline/duration:property"}}{{/crossLink}}.
     * Changing this property directly will have no effect.
     * @property position
     * @type Object
     * @readonly
     **/
    this.position = null;

    // private properties:
    /**
     * @property _paused
     * @type Boolean
     * @protected
     **/
    this._paused = false;

    /**
     * @property _tweens
     * @type Array[Tween]
     * @protected
     **/
    this._tweens = [];

    /**
     * @property _labels
     * @type Object
     * @protected
     **/
    this._labels = null;

    /**
     * @property _labelList
     * @type Array[Object]
     * @protected
     **/
    this._labelList = null;

    /**
     * @property _prevPosition
     * @type Number
     * @default 0
     * @protected
     **/
    this._prevPosition = 0;

    /**
     * @property _prevPos
     * @type Number
     * @default -1
     * @protected
     **/
    this._prevPos = -1;

    /**
     * @property _useTicks
     * @type Boolean
     * @default false
     * @protected
     **/
    this._useTicks = false;
    
    /**
     * Indicates whether the timeline is currently registered with Tween.
     * @property _registered
     * @type {boolean}
     * @default false
     * @protected
     */
    this._registered = false;


    if (props) {
      this._useTicks = props.useTicks;
      this.loop = props.loop;
      this.ignoreGlobalPause = props.ignoreGlobalPause;
      props.onChange&&this.addEventListener("change", props.onChange);
    }
    if (tweens) { this.addTween.apply(this, tweens); }
    this.setLabels(labels);
    if (props&&props.paused) { this._paused=true; }
    else { createjs.Tween._register(this,true); }
    if (props&&props.position!=null) { this.setPosition(props.position, createjs.Tween.NONE); }
    
  };
  
  var p = createjs.extend(Timeline, createjs.EventDispatcher);

  // TODO: deprecated
  // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.

  
// events:
  /**
   * Called whenever the timeline's position changes.
   * @event change
   * @since 0.5.0
   **/


// public methods:
  /**
   * Adds one or more tweens (or timelines) to this timeline. The tweens will be paused (to remove them from the
   * normal ticking system) and managed by this timeline. Adding a tween to multiple timelines will result in
   * unexpected behaviour.
   * @method addTween
   * @param {Tween} ...tween The tween(s) to add. Accepts multiple arguments.
   * @return {Tween} The first tween that was passed in.
   **/
  p.addTween = function(tween) {
    var l = arguments.length;
    if (l > 1) {
      for (var i=0; i<l; i++) { this.addTween(arguments[i]); }
      return arguments[0];
    } else if (l == 0) { return null; }
    this.removeTween(tween);
    this._tweens.push(tween);
    tween.setPaused(true);
    tween._paused = false;
    tween._useTicks = this._useTicks;
    if (tween.duration > this.duration) { this.duration = tween.duration; }
    if (this._prevPos >= 0) { tween.setPosition(this._prevPos, createjs.Tween.NONE); }
    return tween;
  };

  /**
   * Removes one or more tweens from this timeline.
   * @method removeTween
   * @param {Tween} ...tween The tween(s) to remove. Accepts multiple arguments.
   * @return Boolean Returns `true` if all of the tweens were successfully removed.
   **/
  p.removeTween = function(tween) {
    var l = arguments.length;
    if (l > 1) {
      var good = true;
      for (var i=0; i<l; i++) { good = good && this.removeTween(arguments[i]); }
      return good;
    } else if (l == 0) { return false; }

    var tweens = this._tweens;
    var i = tweens.length;
    while (i--) {
      if (tweens[i] == tween) {
        tweens.splice(i, 1);
        if (tween.duration >= this.duration) { this.updateDuration(); }
        return true;
      }
    }
    return false;
  };

  /**
   * Adds a label that can be used with {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}}.
   * @method addLabel
   * @param {String} label The label name.
   * @param {Number} position The position this label represents.
   **/
  p.addLabel = function(label, position) {
    this._labels[label] = position;
    var list = this._labelList;
    if (list) {
      for (var i= 0,l=list.length; i<l; i++) { if (position < list[i].position) { break; } }
      list.splice(i, 0, {label:label, position:position});
    }
  };

  /**
   * Defines labels for use with gotoAndPlay/Stop. Overwrites any previously set labels.
   * @method setLabels
   * @param {Object} o An object defining labels for using {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}}
   * in the form `{labelName:time}` where time is in milliseconds (or ticks if `useTicks` is `true`).
   **/
  p.setLabels = function(o) {
    this._labels = o ?  o : {};
  };

  /**
   * Returns a sorted list of the labels defined on this timeline.
   * @method getLabels
   * @return {Array[Object]} A sorted array of objects with label and position properties.
   **/
  p.getLabels = function() {
    var list = this._labelList;
    if (!list) {
      list = this._labelList = [];
      var labels = this._labels;
      for (var n in labels) {
        list.push({label:n, position:labels[n]});
      }
      list.sort(function (a,b) { return a.position- b.position; });
    }
    return list;
  };

  /**
   * Returns the name of the label on or immediately before the current position. For example, given a timeline with
   * two labels, "first" on frame index 4, and "second" on frame 8, getCurrentLabel would return:
   * <UL>
   *    <LI>null if the current position is 2.</LI>
   *    <LI>"first" if the current position is 4.</LI>
   *    <LI>"first" if the current position is 7.</LI>
   *    <LI>"second" if the current position is 15.</LI>
   * </UL>
   * @method getCurrentLabel
   * @return {String} The name of the current label or null if there is no label
   **/
  p.getCurrentLabel = function() {
    var labels = this.getLabels();
    var pos = this.position;
    var l = labels.length;
    if (l) {
      for (var i = 0; i<l; i++) { if (pos < labels[i].position) { break; } }
      return (i==0) ? null : labels[i-1].label;
    }
    return null;
  };

  /**
   * Unpauses this timeline and jumps to the specified position or label.
   * @method gotoAndPlay
   * @param {String|Number} positionOrLabel The position in milliseconds (or ticks if `useTicks` is `true`)
   * or label to jump to.
   **/
  p.gotoAndPlay = function(positionOrLabel) {
    this.setPaused(false);
    this._goto(positionOrLabel);
  };

  /**
   * Pauses this timeline and jumps to the specified position or label.
   * @method gotoAndStop
   * @param {String|Number} positionOrLabel The position in milliseconds (or ticks if `useTicks` is `true`) or label
   * to jump to.
   **/
  p.gotoAndStop = function(positionOrLabel) {
    this.setPaused(true);
    this._goto(positionOrLabel);
  };

  /**
   * Advances the timeline to the specified position.
   * @method setPosition
   * @param {Number} value The position to seek to in milliseconds (or ticks if `useTicks` is `true`).
   * @param {Number} [actionsMode] parameter specifying how actions are handled. See the Tween {{#crossLink "Tween/setPosition"}}{{/crossLink}}
   * method for more details.
   * @return {Boolean} Returns `true` if the timeline is complete (ie. the full timeline has run & {{#crossLink "Timeline/loop:property"}}{{/crossLink}}
   * is `false`).
   **/
  p.setPosition = function(value, actionsMode) {
    var t = this._calcPosition(value);
    var end = !this.loop && value >= this.duration;
    if (t == this._prevPos) { return end; }
    this._prevPosition = value;
    this.position = this._prevPos = t; // in case an action changes the current frame.
    for (var i=0, l=this._tweens.length; i<l; i++) {
      this._tweens[i].setPosition(t, actionsMode);
      if (t != this._prevPos) { return false; } // an action changed this timeline's position.
    }
    if (end) { this.setPaused(true); }
    this.dispatchEvent("change");
    return end;
  };

  /**
   * Pauses or plays this timeline.
   * @method setPaused
   * @param {Boolean} value Indicates whether the tween should be paused (`true`) or played (`false`).
   **/
  p.setPaused = function(value) {
    this._paused = !!value; 
    createjs.Tween._register(this, !value);
  };

  /**
   * Recalculates the duration of the timeline. The duration is automatically updated when tweens are added or removed,
   * but this method is useful if you modify a tween after it was added to the timeline.
   * @method updateDuration
   **/
  p.updateDuration = function() {
    this.duration = 0;
    for (var i=0,l=this._tweens.length; i<l; i++) {
      var tween = this._tweens[i];
      if (tween.duration > this.duration) { this.duration = tween.duration; }
    }
  };

  /**
   * Advances this timeline by the specified amount of time in milliseconds (or ticks if `useTicks` is `true`).
   * This is normally called automatically by the Tween engine (via the {{#crossLink "Tween/tick:event"}}{{/crossLink}}
   * event), but is exposed for advanced uses.
   * @method tick
   * @param {Number} delta The time to advance in milliseconds (or ticks if useTicks is true).
   **/
  p.tick = function(delta) {
    this.setPosition(this._prevPosition+delta);
  };

  /**
   * If a numeric position is passed, it is returned unchanged. If a string is passed, the position of the
   * corresponding frame label will be returned, or `null` if a matching label is not defined.
   * @method resolve
   * @param {String|Number} positionOrLabel A numeric position value or label string.
   **/
  p.resolve = function(positionOrLabel) {
    var pos = Number(positionOrLabel);
    if (isNaN(pos)) { pos = this._labels[positionOrLabel]; }
    return pos;
  };

  /**
  * Returns a string representation of this object.
  * @method toString
  * @return {String} a string representation of the instance.
  **/
  p.toString = function() {
    return "[Timeline]";
  };

  /**
   * @method clone
   * @protected
   **/
  p.clone = function() {
    throw("Timeline can not be cloned.")
  };

// private methods:
  /**
   * @method _goto
   * @param {String | Number} positionOrLabel
   * @protected
   **/
  p._goto = function(positionOrLabel) {
    var pos = this.resolve(positionOrLabel);
    if (pos != null) { this.setPosition(pos); }
  };
  
  /**
   * @method _calcPosition
   * @param {Number} value
   * @return {Number}
   * @protected
   **/
  p._calcPosition = function(value) {
    if (value < 0) { return 0; }
    if (value < this.duration) { return value; }
    return this.loop ? value%this.duration : this.duration;
  };

  createjs.Timeline = createjs.promote(Timeline, "EventDispatcher");

}());

//##############################################################################
// Ease.js
//##############################################################################

(function() {
  "use strict";

  /**
   * The Ease class provides a collection of easing functions for use with TweenJS. It does not use the standard 4 param
   * easing signature. Instead it uses a single param which indicates the current linear ratio (0 to 1) of the tween.
   *
   * Most methods on Ease can be passed directly as easing functions:
   *
   *      Tween.get(target).to({x:100}, 500, Ease.linear);
   *
   * However, methods beginning with "get" will return an easing function based on parameter values:
   *
   *      Tween.get(target).to({y:200}, 500, Ease.getPowIn(2.2));
   *
   * Please see the <a href="http://www.createjs.com/Demos/TweenJS/Tween_SparkTable">spark table demo</a> for an
   * overview of the different ease types on <a href="http://tweenjs.com">TweenJS.com</a>.
   *
   * <em>Equations derived from work by Robert Penner.</em>
   * @class Ease
   * @static
   **/
  function Ease() {
    throw "Ease cannot be instantiated.";
  }


// static methods and properties
  /**
   * @method linear
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.linear = function(t) { return t; };

  /**
   * Identical to linear.
   * @method none
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.none = Ease.linear;

  /**
   * Mimics the simple -100 to 100 easing in Flash Pro.
   * @method get
   * @param {Number} amount A value from -1 (ease in) to 1 (ease out) indicating the strength and direction of the ease.
   * @static
   * @return {Function}
   **/
  Ease.get = function(amount) {
    if (amount < -1) { amount = -1; }
    if (amount > 1) { amount = 1; }
    return function(t) {
      if (amount==0) { return t; }
      if (amount<0) { return t*(t*-amount+1+amount); }
      return t*((2-t)*amount+(1-amount));
    };
  };

  /**
   * Configurable exponential ease.
   * @method getPowIn
   * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease).
   * @static
   * @return {Function}
   **/
  Ease.getPowIn = function(pow) {
    return function(t) {
      return Math.pow(t,pow);
    };
  };

  /**
   * Configurable exponential ease.
   * @method getPowOut
   * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease).
   * @static
   * @return {Function}
   **/
  Ease.getPowOut = function(pow) {
    return function(t) {
      return 1-Math.pow(1-t,pow);
    };
  };

  /**
   * Configurable exponential ease.
   * @method getPowInOut
   * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease).
   * @static
   * @return {Function}
   **/
  Ease.getPowInOut = function(pow) {
    return function(t) {
      if ((t*=2)<1) return 0.5*Math.pow(t,pow);
      return 1-0.5*Math.abs(Math.pow(2-t,pow));
    };
  };

  /**
   * @method quadIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quadIn = Ease.getPowIn(2);
  /**
   * @method quadOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quadOut = Ease.getPowOut(2);
  /**
   * @method quadInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quadInOut = Ease.getPowInOut(2);

  /**
   * @method cubicIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.cubicIn = Ease.getPowIn(3);
  /**
   * @method cubicOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.cubicOut = Ease.getPowOut(3);
  /**
   * @method cubicInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.cubicInOut = Ease.getPowInOut(3);

  /**
   * @method quartIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quartIn = Ease.getPowIn(4);
  /**
   * @method quartOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quartOut = Ease.getPowOut(4);
  /**
   * @method quartInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quartInOut = Ease.getPowInOut(4);

  /**
   * @method quintIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quintIn = Ease.getPowIn(5);
  /**
   * @method quintOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quintOut = Ease.getPowOut(5);
  /**
   * @method quintInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.quintInOut = Ease.getPowInOut(5);

  /**
   * @method sineIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.sineIn = function(t) {
    return 1-Math.cos(t*Math.PI/2);
  };

  /**
   * @method sineOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.sineOut = function(t) {
    return Math.sin(t*Math.PI/2);
  };

  /**
   * @method sineInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.sineInOut = function(t) {
    return -0.5*(Math.cos(Math.PI*t) - 1);
  };

  /**
   * Configurable "back in" ease.
   * @method getBackIn
   * @param {Number} amount The strength of the ease.
   * @static
   * @return {Function}
   **/
  Ease.getBackIn = function(amount) {
    return function(t) {
      return t*t*((amount+1)*t-amount);
    };
  };
  /**
   * @method backIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.backIn = Ease.getBackIn(1.7);

  /**
   * Configurable "back out" ease.
   * @method getBackOut
   * @param {Number} amount The strength of the ease.
   * @static
   * @return {Function}
   **/
  Ease.getBackOut = function(amount) {
    return function(t) {
      return (--t*t*((amount+1)*t + amount) + 1);
    };
  };
  /**
   * @method backOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.backOut = Ease.getBackOut(1.7);

  /**
   * Configurable "back in out" ease.
   * @method getBackInOut
   * @param {Number} amount The strength of the ease.
   * @static
   * @return {Function}
   **/
  Ease.getBackInOut = function(amount) {
    amount*=1.525;
    return function(t) {
      if ((t*=2)<1) return 0.5*(t*t*((amount+1)*t-amount));
      return 0.5*((t-=2)*t*((amount+1)*t+amount)+2);
    };
  };
  /**
   * @method backInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.backInOut = Ease.getBackInOut(1.7);

  /**
   * @method circIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.circIn = function(t) {
    return -(Math.sqrt(1-t*t)- 1);
  };

  /**
   * @method circOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.circOut = function(t) {
    return Math.sqrt(1-(--t)*t);
  };

  /**
   * @method circInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.circInOut = function(t) {
    if ((t*=2) < 1) return -0.5*(Math.sqrt(1-t*t)-1);
    return 0.5*(Math.sqrt(1-(t-=2)*t)+1);
  };

  /**
   * @method bounceIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.bounceIn = function(t) {
    return 1-Ease.bounceOut(1-t);
  };

  /**
   * @method bounceOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.bounceOut = function(t) {
    if (t < 1/2.75) {
      return (7.5625*t*t);
    } else if (t < 2/2.75) {
      return (7.5625*(t-=1.5/2.75)*t+0.75);
    } else if (t < 2.5/2.75) {
      return (7.5625*(t-=2.25/2.75)*t+0.9375);
    } else {
      return (7.5625*(t-=2.625/2.75)*t +0.984375);
    }
  };

  /**
   * @method bounceInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.bounceInOut = function(t) {
    if (t<0.5) return Ease.bounceIn (t*2) * .5;
    return Ease.bounceOut(t*2-1)*0.5+0.5;
  };

  /**
   * Configurable elastic ease.
   * @method getElasticIn
   * @param {Number} amplitude
   * @param {Number} period
   * @static
   * @return {Function}
   **/
  Ease.getElasticIn = function(amplitude,period) {
    var pi2 = Math.PI*2;
    return function(t) {
      if (t==0 || t==1) return t;
      var s = period/pi2*Math.asin(1/amplitude);
      return -(amplitude*Math.pow(2,10*(t-=1))*Math.sin((t-s)*pi2/period));
    };
  };
  /**
   * @method elasticIn
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.elasticIn = Ease.getElasticIn(1,0.3);

  /**
   * Configurable elastic ease.
   * @method getElasticOut
   * @param {Number} amplitude
   * @param {Number} period
   * @static
   * @return {Function}
   **/
  Ease.getElasticOut = function(amplitude,period) {
    var pi2 = Math.PI*2;
    return function(t) {
      if (t==0 || t==1) return t;
      var s = period/pi2 * Math.asin(1/amplitude);
      return (amplitude*Math.pow(2,-10*t)*Math.sin((t-s)*pi2/period )+1);
    };
  };
  /**
   * @method elasticOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.elasticOut = Ease.getElasticOut(1,0.3);

  /**
   * Configurable elastic ease.
   * @method getElasticInOut
   * @param {Number} amplitude
   * @param {Number} period
   * @static
   * @return {Function}
   **/
  Ease.getElasticInOut = function(amplitude,period) {
    var pi2 = Math.PI*2;
    return function(t) {
      var s = period/pi2 * Math.asin(1/amplitude);
      if ((t*=2)<1) return -0.5*(amplitude*Math.pow(2,10*(t-=1))*Math.sin( (t-s)*pi2/period ));
      return amplitude*Math.pow(2,-10*(t-=1))*Math.sin((t-s)*pi2/period)*0.5+1;
    };
  };
  /**
   * @method elasticInOut
   * @param {Number} t
   * @static
   * @return {Number}
   **/
  Ease.elasticInOut = Ease.getElasticInOut(1,0.3*1.5);

  createjs.Ease = Ease;

}());

//##############################################################################
// MotionGuidePlugin.js
//##############################################################################

(function() {
  "use strict";

  /**
   * A TweenJS plugin for working with motion guides.
   *
   * To use, install the plugin after TweenJS has loaded. Next tween the 'guide' property with an object as detailed below.
   *
   *       createjs.MotionGuidePlugin.install();
   *
   * <h4>Example</h4>
   *
   *      // Using a Motion Guide
   *      createjs.Tween.get(target).to({guide:{ path:[0,0, 0,200,200,200, 200,0,0,0] }},7000);
   *      // Visualizing the line
   *      graphics.moveTo(0,0).curveTo(0,200,200,200).curveTo(200,0,0,0);
   *
   * Each path needs pre-computation to ensure there's fast performance. Because of the pre-computation there's no
   * built in support for path changes mid tween. These are the Guide Object's properties:<UL>
   *      <LI> path: Required, Array : The x/y points used to draw the path with a moveTo and 1 to n curveTo calls.</LI>
   *      <LI> start: Optional, 0-1 : Initial position, default 0 except for when continuing along the same path.</LI>
   *      <LI> end: Optional, 0-1 : Final position, default 1 if not specified.</LI>
   *      <LI> orient: Optional, string : "fixed"/"auto"/"cw"/"ccw"<UL>
   *        <LI>"fixed" forces the object to face down the path all movement (relative to start rotation),</LI>
   *          <LI>"auto" rotates the object along the path relative to the line.</LI>
   *          <LI>"cw"/"ccw" force clockwise or counter clockwise rotations including flash like behaviour</LI>
   *    </UL></LI>
   * </UL>
   * Guide objects should not be shared between tweens even if all properties are identical, the library stores
   * information on these objects in the background and sharing them can cause unexpected behaviour. Values
   * outside 0-1 range of tweens will be a "best guess" from the appropriate part of the defined curve.
   *
   * @class MotionGuidePlugin
   * @constructor
   **/
  function MotionGuidePlugin() {
    throw("MotionGuidePlugin cannot be instantiated.")
  };


// static properties:
  /**
   * @property priority
   * @protected
   * @static
   **/
  MotionGuidePlugin.priority = 0; // high priority, should run sooner

  /**
   * @property temporary variable storage
   * @private
   * @static
   */
  MotionGuidePlugin._rotOffS;
  /**
   * @property temporary variable storage
   * @private
   * @static
   */
  MotionGuidePlugin._rotOffE;
  /**
   * @property temporary variable storage
   * @private
   * @static
   */
  MotionGuidePlugin._rotNormS;
  /**
   * @property temporary variable storage
   * @private
   * @static
   */
  MotionGuidePlugin._rotNormE;


// static methods
  /**
   * Installs this plugin for use with TweenJS. Call this once after TweenJS is loaded to enable this plugin.
   * @method install
   * @static
   **/
  MotionGuidePlugin.install = function() {
    createjs.Tween.installPlugin(MotionGuidePlugin, ["guide", "x", "y", "rotation"]);
    return createjs.Tween.IGNORE;
  };

  /**
   * @method init
   * @protected
   * @static
   **/
  MotionGuidePlugin.init = function(tween, prop, value) {
    var target = tween.target;
    if(!target.hasOwnProperty("x")){ target.x = 0; }
    if(!target.hasOwnProperty("y")){ target.y = 0; }
    if(!target.hasOwnProperty("rotation")){ target.rotation = 0; }

    if(prop=="rotation"){ tween.__needsRot = true; }
    return prop=="guide"?null:value;
  };

  /**
   * @method step
   * @protected
   * @static
   **/
  MotionGuidePlugin.step = function(tween, prop, startValue, endValue, injectProps) {
    // other props
    if(prop == "rotation"){
      tween.__rotGlobalS = startValue;
      tween.__rotGlobalE = endValue;
      MotionGuidePlugin.testRotData(tween, injectProps);
    }
    if(prop != "guide"){ return endValue; }

    // guide only information - Start -
    var temp, data = endValue;
    if(!data.hasOwnProperty("path")){ data.path = []; }
    var path = data.path;
    if(!data.hasOwnProperty("end")){ data.end = 1; }
    if(!data.hasOwnProperty("start")){
      data.start = (startValue&&startValue.hasOwnProperty("end")&&startValue.path===path)?startValue.end:0;
    }

    // Figure out subline information
    if(data.hasOwnProperty("_segments") && data._length){ return endValue; }
    var l = path.length;
    var accuracy = 10;    // Adjust to improve line following precision but sacrifice performance (# of seg)
    if(l >= 6 && (l-2) % 4 == 0){ // Enough points && contains correct number per entry ignoring start
      data._segments = [];
      data._length = 0;
      for(var i=2; i<l; i+=4){
        var sx = path[i-2], sy = path[i-1];
        var cx = path[i+0], cy = path[i+1];
        var ex = path[i+2], ey = path[i+3];
        var oldX = sx, oldY = sy;
        var tempX, tempY, total = 0;
        var sublines = [];
        for(var j=1; j<=accuracy; j++){
          var t = j/accuracy;
          var inv = 1 - t;
          tempX = inv*inv * sx + 2 * inv * t * cx + t*t * ex;
          tempY = inv*inv * sy + 2 * inv * t * cy + t*t * ey;
          total += sublines[sublines.push(Math.sqrt((temp=tempX-oldX)*temp + (temp=tempY-oldY)*temp))-1];
          oldX = tempX;
          oldY = tempY;
        }
        data._segments.push(total);
        data._segments.push(sublines);
        data._length += total;
      }
    } else {
      throw("invalid 'path' data, please see documentation for valid paths");
    }

    // Setup x/y tweens
    temp = data.orient;
    data.orient = true;
    var o = {};
    MotionGuidePlugin.calc(data, data.start, o);
    tween.__rotPathS = Number(o.rotation.toFixed(5));
    MotionGuidePlugin.calc(data, data.end, o);
    tween.__rotPathE = Number(o.rotation.toFixed(5));
    data.orient = false;  //here and now we don't know if we need to
    MotionGuidePlugin.calc(data, data.end, injectProps);
    data.orient = temp;

    // Setup rotation properties
    if(!data.orient){ return endValue; }
    tween.__guideData = data;
    MotionGuidePlugin.testRotData(tween, injectProps);
    return endValue;
  };

  /**
   * @method testRotData
   * @protected
   * @static
   **/
  MotionGuidePlugin.testRotData = function(tween, injectProps){

    // no rotation informat? if we need it come back, if we don't use 0 & ensure we have guide data
    if(tween.__rotGlobalS === undefined || tween.__rotGlobalE === undefined){
      if(tween.__needsRot){ return; }
      if(tween._curQueueProps.rotation !== undefined){
        tween.__rotGlobalS = tween.__rotGlobalE = tween._curQueueProps.rotation;
      } else {
        tween.__rotGlobalS = tween.__rotGlobalE = injectProps.rotation = tween.target.rotation || 0;
      }
    }
    if(tween.__guideData === undefined){ return; }

    // Process rotation properties
    var data = tween.__guideData;
    var rotGlobalD = tween.__rotGlobalE - tween.__rotGlobalS;
    var rotPathD = tween.__rotPathE - tween.__rotPathS;
    var rot = rotGlobalD - rotPathD;

    if(data.orient == "auto"){
      if(rot > 180){      rot -= 360; }
      else if(rot < -180){  rot += 360; }

    } else if(data.orient == "cw"){
      while(rot < 0){ rot += 360; }
      if(rot == 0 && rotGlobalD > 0 && rotGlobalD != 180){ rot += 360; }

    } else if(data.orient == "ccw"){
      rot = rotGlobalD - ((rotPathD > 180)?(360-rotPathD):(rotPathD));  // sign flipping on path
      while(rot > 0){ rot -= 360; }
      if(rot == 0 && rotGlobalD < 0 && rotGlobalD != -180){ rot -= 360; }
    }

    data.rotDelta = rot;
    data.rotOffS = tween.__rotGlobalS - tween.__rotPathS;

    // reset
    tween.__rotGlobalS = tween.__rotGlobalE = tween.__guideData = tween.__needsRot = undefined;
  };

  /**
   * @method tween
   * @protected
   * @static
   **/
  MotionGuidePlugin.tween = function(tween, prop, value, startValues, endValues, ratio, wait, end) {
    var data = endValues.guide;
    if(data == undefined || data === startValues.guide){ return value; }
    if(data.lastRatio != ratio){
      // first time through so calculate what I need to
      var t = ((data.end-data.start)*(wait?data.end:ratio)+data.start);
      MotionGuidePlugin.calc(data, t, tween.target);
      switch(data.orient){
        case "cw":    // mix in the original rotation
        case "ccw":
        case "auto": tween.target.rotation += data.rotOffS + data.rotDelta*ratio; break;
        case "fixed": // follow fixed behaviour to solve potential issues
        default: tween.target.rotation += data.rotOffS; break;
      }
      data.lastRatio = ratio;
    }
    if(prop == "rotation" && ((!data.orient) || data.orient == "false")){ return value; }
    return tween.target[prop];
  };

  /**
   * Determine the appropriate x/y/rotation information about a path for a given ratio along the path.
   * Assumes a path object with all optional parameters specified.
   * @param data Data object you would pass to the "guide:" property in a Tween
   * @param ratio 0-1 Distance along path, values outside 0-1 are "best guess"
   * @param target Object to copy the results onto, will use a new object if not supplied.
   * @return {Object} The target object or a new object w/ the tweened properties
   * @static
   */
  MotionGuidePlugin.calc = function(data, ratio, target) {
    if(data._segments == undefined){ MotionGuidePlugin.validate(data); }
    if(target == undefined){ target = {x:0, y:0, rotation:0}; }
    var seg = data._segments;
    var path = data.path;

    // find segment
    var pos = data._length * ratio;
    var cap = seg.length - 2;
    var n = 0;
    while(pos > seg[n] && n < cap){
      pos -= seg[n];
      n+=2;
    }

    // find subline
    var sublines = seg[n+1];
    var i = 0;
    cap = sublines.length-1;
    while(pos > sublines[i] && i < cap){
      pos -= sublines[i];
      i++;
    }
    var t = (i/++cap)+(pos/(cap*sublines[i]));

    // find x/y
    n = (n*2)+2;
    var inv = 1 - t;
    target.x = inv*inv * path[n-2] + 2 * inv * t * path[n+0] + t*t * path[n+2];
    target.y = inv*inv * path[n-1] + 2 * inv * t * path[n+1] + t*t * path[n+3];

    // orientation
    if(data.orient){
      target.rotation = 57.2957795 * Math.atan2(
        (path[n+1]-path[n-1])*inv + (path[n+3]-path[n+1])*t,
        (path[n+0]-path[n-2])*inv + (path[n+2]-path[n+0])*t);
    }

    return target;
  };

  createjs.MotionGuidePlugin = MotionGuidePlugin;

}());

//##############################################################################
// version.js
//##############################################################################

(function() {
  "use strict";

  /**
   * Static class holding library specific information such as the version and buildDate of
   * the library.
   * @class TweenJS
   **/
  var s = createjs.TweenJS = createjs.TweenJS || {};

  /**
   * The version string for this release.
   * @property version
   * @type String
   * @static
   **/
  s.version = /*=version*/"0.6.1"; // injected by build process

  /**
   * The build date for this release in UTC format.
   * @property buildDate
   * @type String
   * @static
   **/
  s.buildDate = /*=date*/"Thu, 21 May 2015 16:17:37 GMT"; // injected by build process

})();