Transferred from the Adobe Open Source Subversion Repository

Revision: 17710
Author:   clucier@adobe.com
Date:     2010-09-15T11:23:04.637186Z

Log Message:
-----------
Better support for DisplayObject based sources. Take two.

QE notes: None
Doc notes: None
Bugs: SDK-27822
Reviewer: Glenn
Tests run: Checkin, Cyclone Server
Is noteworthy for integration: No.

Modified Paths:
--------------
/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/primitives/BitmapImage.as

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1285625 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/primitives/BitmapImage.as
+++ frameworks/projects/spark/src/spark/primitives/BitmapImage.as
@@ -11,1739 +11,1782 @@

 package spark.primitives
 {
-
-import flash.display.Bitmap;
-import flash.display.BitmapData;
-import flash.display.DisplayObject;
-import flash.display.DisplayObjectContainer;
-import flash.display.Graphics;
-import flash.display.Loader;
-import flash.display.LoaderInfo;
-import flash.display.Sprite;
-import flash.events.Event;
-import flash.events.HTTPStatusEvent;
-import flash.events.IOErrorEvent;
-import flash.events.ProgressEvent;
-import flash.events.SecurityErrorEvent;
-import flash.geom.Matrix;
-import flash.geom.Point;
-import flash.geom.Rectangle;
-import flash.net.URLRequest;
-import flash.system.ApplicationDomain;
-import flash.system.LoaderContext;
-import flash.utils.ByteArray;
-
-import mx.core.mx_internal;
-import mx.events.FlexEvent;
-import mx.graphics.BitmapFillMode;
-import mx.graphics.BitmapScaleMode;
-import mx.graphics.BitmapSmoothingQuality;
-
-import spark.core.ContentRequest;
-import spark.core.DisplayObjectSharingMode;
-import spark.core.IContentLoader;
-import spark.layouts.HorizontalAlign;
-import spark.layouts.VerticalAlign;
-import spark.primitives.supportClasses.GraphicElement;
-
-use namespace mx_internal;
-
-//--------------------------------------
-//  Events
-//--------------------------------------
-
-/**
- *  Dispatched when content loading is complete. This
- *  event is only dispatched for url and ByteArray based
- *  sources (those sources requiring a Loader).
- *
- *
Note that for content loaded via Loader, both
- *  ready and complete events
- *  are dispatched.
  For other source types such as
- *  embeds, only ready is dispatched.
- *
- *  @eventType flash.events.Event.COMPLETE
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="complete", type="flash.events.Event")]
-
-/**
- *  Dispatched when a network request is made over HTTP
- *  and Flash Player or AIR can detect the HTTP status code.
- *
- *  @eventType flash.events.HTTPStatusEvent.HTTP_STATUS
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="httpStatus", type="flash.events.HTTPStatusEvent")]
-
-/**
- *  Dispatched when an input/output error occurs.
- *  @see flash.events.IOErrorEvent
- *
- *  @eventType flash.events.IOErrorEvent.IO_ERROR
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="ioError", type="flash.events.IOErrorEvent")]
-
-/**
- *  Dispatched when content is loading.
- *
- *
Note:
- *  The progress event is not guaranteed to be dispatched.
- *  The complete event may be received, without any
- *  progress events being dispatched.
- *  This can happen when the loaded content is a local file.

- *
- *  @eventType flash.events.ProgressEvent.PROGRESS
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="progress", type="flash.events.ProgressEvent")]
-
-/**
- *  Dispatched when content loading is complete.  Unlike the
- *  complete event, this event is dispatched for
- *  all source types.
- *
- *
Note that for content loaded via Loader, both
- *  ready and complete events
- *  are dispatched.
  For other source types such as
- *  embeds, only ready is dispatched.
- *
- *  @eventType mx.events.FlexEvent.READY
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="ready", type="mx.events.FlexEvent")]
-
-/**
- *  Dispatched when a security error occurs.
- *  @see flash.events.SecurityErrorEvent
- *
- *  @eventType flash.events.SecurityErrorEvent.SECURITY_ERROR
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.5
- */
-[Event(name="securityError", type="flash.events.SecurityErrorEvent")]
-
-/**
- *  A BitmapImage element defines a rectangular region in its parent element's
- *  coordinate space, filled with bitmap data drawn from a source file or
- *  source URL.
- *
- *  @includeExample examples/BitmapImageExample.mxml
- *
- *  @langversion 3.0
- *  @playerversion Flash 10
- *  @playerversion AIR 2.0
- *  @productversion Flex 4.0
- */
-public class BitmapImage extends GraphicElement
-{
-    include "../core/Version.as";
-
-    //--------------------------------------------------------------------------
-    //
-    //  Constructor
-    //
-    //--------------------------------------------------------------------------
+
+    import flash.display.Bitmap;
+    import flash.display.BitmapData;
+    import flash.display.DisplayObject;
+    import flash.display.DisplayObjectContainer;
+    import flash.display.Graphics;
+    import flash.display.Loader;
+    import flash.display.LoaderInfo;
+    import flash.display.Sprite;
+    import flash.events.Event;
+    import flash.events.HTTPStatusEvent;
+    import flash.events.IOErrorEvent;
+    import flash.events.ProgressEvent;
+    import flash.events.SecurityErrorEvent;
+    import flash.geom.Matrix;
+    import flash.geom.Point;
+    import flash.geom.Rectangle;
+    import flash.net.URLRequest;
+    import flash.system.ApplicationDomain;
+    import flash.system.LoaderContext;
+    import flash.utils.ByteArray;
+
+    import mx.core.IInvalidating;
+    import mx.core.mx_internal;
+    import mx.events.FlexEvent;
+    import mx.graphics.BitmapFillMode;
+    import mx.graphics.BitmapScaleMode;
+    import mx.graphics.BitmapSmoothingQuality;
+
+    import spark.core.ContentRequest;
+    import spark.core.DisplayObjectSharingMode;
+    import spark.core.IContentLoader;
+    import spark.layouts.HorizontalAlign;
+    import spark.layouts.VerticalAlign;
+    import spark.primitives.supportClasses.GraphicElement;
+
+    use namespace mx_internal;
+
+    //--------------------------------------
+    //  Events
+    //--------------------------------------

     /**
-     *  Constructor.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    public function BitmapImage()
-    {
-        super();
-
-        // Typically, this should not be mirrored.
-        layoutDirection = "ltr";
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    //  Properties
-    //
-    //--------------------------------------------------------------------------
-
-    private var _scaleGridBottom:Number;
-    private var _scaleGridLeft:Number;
-    private var _scaleGridRight:Number;
-    private var _scaleGridTop:Number;
-    private var bitmapDataCreated:Boolean;
-    private static var matrix:Matrix = new Matrix();
-    private var cachedSourceGrid:Array;
-    private var cachedDestGrid:Array;
-    private var imageWidth:Number = NaN;
-    private var imageHeight:Number = NaN;
-    private var loadedContent:DisplayObject;
-    private var loadingContent:Object;
-    private var previousUnscaledWidth:Number;
-    private var previousUnscaledHeight:Number;
-    private var sourceInvalid:Boolean;
-    private var loadFailed:Boolean;
-
-    //----------------------------------
-    //  bitmapData
-    //----------------------------------
-
-    private var _bitmapData:BitmapData;
-
-    /**
-     *  Returns a copy of the BitmapData object representing
-     *  the currently loaded image content (unscaled).  This property
-     *  is null for untrusted cross domain content.
+     *  Dispatched when content loading is complete. This
+     *  event is only dispatched for url and ByteArray based
+     *  sources (those sources requiring a Loader).
      *
-     *  @default null
+     *
Note that for content loaded via Loader, both
+     *  ready and complete events
+     *  are dispatched.
  For other source types such as
+     *  embeds, only ready is dispatched.
+     *
+     *  @eventType flash.events.Event.COMPLETE
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
      *  @playerversion AIR 2.0
      *  @productversion Flex 4.5
      */
-    public function get bitmapData():BitmapData
-    {
-        return _bitmapData ? _bitmapData.clone() : _bitmapData;
-    }
-
-    //----------------------------------
-    //  bytesLoaded
-    //----------------------------------
-
-    private var _bytesLoaded:Number = NaN;
+    [Event(name="complete", type="flash.events.Event")]

     /**
-     *  The number of bytes of the image already loaded.
-     *  Only relevant for images loaded by request URL.
+     *  Dispatched when a network request is made over HTTP
+     *  and Flash Player or AIR can detect the HTTP status code.
      *
-     *  @default NaN
+     *  @eventType flash.events.HTTPStatusEvent.HTTP_STATUS
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
      *  @playerversion AIR 2.0
      *  @productversion Flex 4.5
      */
-    public function get bytesLoaded():Number
-    {
-        return _bytesLoaded;
-    }
-
-    //----------------------------------
-    //  bytesTotal
-    //----------------------------------
-
-    private var _bytesTotal:Number = NaN;
+    [Event(name="httpStatus", type="flash.events.HTTPStatusEvent")]

     /**
-     *  The total image data in bytes loaded or pending load.
-     *  Only relevant for images loaded by request URL.
-     *
-     *  @default NaN
+     *  Dispatched when an input/output error occurs.
+     *  @see flash.events.IOErrorEvent
+     *
+     *  @eventType flash.events.IOErrorEvent.IO_ERROR
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
      *  @playerversion AIR 2.0
      *  @productversion Flex 4.5
      */
-    public function get bytesTotal():Number
-    {
-        return _bytesTotal;
-    }
-
-    //----------------------------------
-    //  clearOnLoad
-    //----------------------------------
-
-    private var _clearOnLoad:Boolean = true;
+    [Event(name="ioError", type="flash.events.IOErrorEvent")]

     /**
-     *  Denotes whether or not to clear previous
-     *  image content prior to loading new content.
-     *
-     *  @default true
+     *  Dispatched when content is loading.
+     *
+     *
Note:
+     *  The progress event is not guaranteed to be dispatched.
+     *  The complete event may be received, without any
+     *  progress events being dispatched.
+     *  This can happen when the loaded content is a local file.

+     *
+     *  @eventType flash.events.ProgressEvent.PROGRESS
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
      *  @playerversion AIR 2.0
      *  @productversion Flex 4.5
      */
-    public function get clearOnLoad():Boolean
-    {
-        return _clearOnLoad;
-    }
+    [Event(name="progress", type="flash.events.ProgressEvent")]

     /**
-     *  @private
-     */
-    public function set clearOnLoad(value:Boolean):void
-    {
-        _clearOnLoad = value;
-    }
-
-    //----------------------------------
-    //  contentLoaderGrouping
-    //----------------------------------
-
-    private var _contentLoaderGrouping:String;
-
-    /**
-     *  Optional content grouping identifier to pass to the an
-     *  associated IContentLoader instance's load() method.
-     *  This property is only considered when a valid contentLoader
-     *  is assigned.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get contentLoaderGrouping():String
-    {
-        return _contentLoaderGrouping;
-    }
-
-    /**
-     *  @private
-     */
-    public function set contentLoaderGrouping(value:String):void
-    {
-        if (value != _contentLoaderGrouping)
-        {
-            _contentLoaderGrouping = value;
-            invalidateProperties();
-        }
-    }
-
-    //----------------------------------
-    //  contentLoader
-    //----------------------------------
-
-    private var _contentLoader:IContentLoader;
-    private var contentLoaderInvalid:Boolean;
-
-    /**
-     *  Optional custom image loader (e.g. image cache or queue) to
-     *  associate with content loader client.
-     *
-     *  @default null
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get contentLoader():IContentLoader
-    {
-        return _contentLoader;
-    }
-
-    /**
-     *  @private
-     */
-    public function set contentLoader(value:IContentLoader):void
-    {
-        if (value != _contentLoader)
-        {
-            _contentLoader = value;
-            contentLoaderInvalid = true;
-            invalidateProperties();
-        }
-    }
-
-    //----------------------------------
-    //  fillMode
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    protected var _fillMode:String = BitmapFillMode.SCALE;
-
-    [Inspectable(category="General", enumeration="clip,repeat,scale", defaultValue="scale")]
-
-    /**
-     *  The fillMode determines how the bitmap fills in the dimensions. If you set the value
-     *  of this property in a tag, use the string (such as "repeat"). If you set the value of
-     *  this property in ActionScript, use the constant (such as BitmapFillMode.CLIP).
-     *
-     *  When set to BitmapFillMode.CLIP ("clip"), the bitmap
-     *  ends at the edge of the region.
-     *
-     *  When set to BitmapFillMode.REPEAT ("repeat"), the bitmap
-     *  repeats to fill the region.
+     *  Dispatched when content loading is complete.  Unlike the
+     *  complete event, this event is dispatched for
+     *  all source types.
+     *
+     *
Note that for content loaded via Loader, both
+     *  ready and complete events
+     *  are dispatched.
  For other source types such as
+     *  embeds, only ready is dispatched.
      *
-     *  When set to BitmapFillMode.SCALE ("scale"), the bitmap
-     *  stretches to fill the region.
-     *
-     *  @default BitmapFillMode.SCALE
+     *  @eventType mx.events.FlexEvent.READY
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
      */
-    public function get fillMode():String
-    {
-        return _fillMode;
-    }
+    [Event(name="ready", type="mx.events.FlexEvent")]

     /**
-     *  @private
-     */
-    public function set fillMode(value:String):void
-    {
-        if (value != _fillMode)
-        {
-            _fillMode = value;
-            invalidateDisplayList();
-        }
-    }
-
-    //----------------------------------
-    //  horizontalAlign
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    private var _horizontalAlign:String = HorizontalAlign.CENTER;
-
-    [Inspectable(category="General", enumeration="left,right,center", defaultValue="center")]
-
-    /**
-     *  The horizontal alignment of the content when it does not have
-     *  a one-to-one aspect ratio and scaleMode is set to
-     *  BitmapScaleMode.LETTERBOX.
-     *
-     *
Can be one of HorizontalAlign.LEFT ("left"),
-     *  HorizontalAlign.RIGHT ("right"), or
-     *  HorizontalAlign.CENTER ("center").

-     *
-     *
This property is only applicable when fillMode is set to
-     *  to BitmapFillMode.SCALE ("scale").

-     *
-     *  @default HorizontalAlign.CENTER
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    public function get horizontalAlign():String
-    {
-        return _horizontalAlign;
-    }
-
-    /**
-     *  @private
-     */
-    public function set horizontalAlign(value:String):void
-    {
-        if (value == _horizontalAlign)
-            return;
-
-        _horizontalAlign = value;
-        invalidateDisplayList();
-    }
-
-    /**
-     *  @private
-     */
-    private function getHorizontalAlignValue():Number
-    {
-        if (_horizontalAlign == HorizontalAlign.LEFT)
-            return 0;
-        else if (_horizontalAlign == HorizontalAlign.RIGHT)
-            return 1;
-        else
-            return 0.5;
-    }
-
-    //----------------------------------
-    //  preliminaryHeight
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    private var _preliminaryHeight:Number = NaN;
-
-    /**
-     *  Provides an estimate to use for height when the "measured" bounds
-     *  of the image is requested by layout, but the image data has
-     *  yet to complete loading. When NaN the measured height is 0 until
-     *  the image has finished loading.
-     *
-     *  @default NaN
+     *  Dispatched when a security error occurs.
+     *  @see flash.events.SecurityErrorEvent
+     *
+     *  @eventType flash.events.SecurityErrorEvent.SECURITY_ERROR
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
+     *  @playerversion AIR 2.0
      *  @productversion Flex 4.5
      */
-    public function get preliminaryHeight():Number
-    {
-        return _preliminaryHeight;
-    }
+    [Event(name="securityError", type="flash.events.SecurityErrorEvent")]

     /**
-     *  @private
-     */
-    public function set preliminaryHeight(value:Number):void
-    {
-        if (value != _preliminaryHeight)
-        {
-            _preliminaryHeight = value;
-            invalidateSize();
-        }
-    }
-
-    //----------------------------------
-    //  preliminaryWidth
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    private var _preliminaryWidth:Number = NaN;
-
-    /**
-     *  Provides an estimate to use for width when the "measured" bounds
-     *  of the image is requested by layout, but the image data has
-     *  yet to complete loading. When NaN the measured width is 0 until
-     *  the image has finished loading.
-     *
-     *  @default NaN
+     *  A BitmapImage element defines a rectangular region in its parent element's
+     *  coordinate space, filled with bitmap data drawn from a source file or
+     *  source URL.
+     *
+     *  @includeExample examples/BitmapImageExample.mxml
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.0
      */
-    public function get preliminaryWidth():Number
+    public class BitmapImage extends GraphicElement
     {
-        return _preliminaryWidth;
-    }
-
-    /**
-     *  @private
-     */
-    public function set preliminaryWidth(value:Number):void
-    {
-        if (value != _preliminaryWidth)
-        {
-            _preliminaryWidth = value;
-            invalidateSize();
-        }
-    }
-
-    //----------------------------------
-    //  scaleMode
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    private var _scaleMode:String = BitmapScaleMode.STRETCH;
-
-    [Inspectable(category="General", enumeration="stretch,letterbox", defaultValue="stretch")]
-
-    /**
-     *  Determines how the image is scaled when fillMode is set to
-     *  BitmapFillMode.SCALE.
-     *
-     *
When set to BitmapScaleMode.STRETCH ("stretch"),
-     *  the image is stretched to fit.

-     *
-     *
When set to BitmapScaleMode.LETTERBOX ("letterbox"),
-     *  the image is scaled with respect to the original unscaled image's
-     *  aspect ratio.

-     *
-     *  @default BitmapScaleMode.STRETCH
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10.1
-     *  @playerversion AIR 2.0
-     *  @productversion Flex 4.5
-     */
-    public function get scaleMode():String
-    {
-        return _scaleMode;
-    }
-
-    /**
-     *  @private
-     */
-    public function set scaleMode(value:String):void
-    {
-        if (value == _scaleMode)
-            return;
-
-        _scaleMode = value;
-        invalidateDisplayList();
-    }
-
-    //----------------------------------
-    //  smooth
-    //----------------------------------
-
-    private var _smooth:Boolean = false;
-
-    [Inspectable(category="General", enumeration="true,false", defaultValue="false")]
-
-    /**
-     *  @copy flash.display.GraphicsBitmapFill#smooth
-     *
-     *  @default false
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    public function set smooth(value:Boolean):void
-    {
-        if (value != _smooth)
-        {
-            _smooth = value;
+        include "../core/Version.as";
+
+        //--------------------------------------------------------------------------
+        //
+        //  Constructor
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  Constructor.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        public function BitmapImage()
+        {
+            super();
+
+            // Typically, this should not be mirrored.
+            layoutDirection = "ltr";
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  Properties
+        //
+        //--------------------------------------------------------------------------
+
+        private var _scaleGridBottom:Number;
+        private var _scaleGridLeft:Number;
+        private var _scaleGridRight:Number;
+        private var _scaleGridTop:Number;
+        private var bitmapDataCreated:Boolean;
+        private static var matrix:Matrix = new Matrix();
+        private var cachedSourceGrid:Array;
+        private var cachedDestGrid:Array;
+        private var imageWidth:Number = NaN;
+        private var imageHeight:Number = NaN;
+        private var loadedContent:DisplayObject;
+        private var loadingContent:Object;
+        private var previousUnscaledWidth:Number;
+        private var previousUnscaledHeight:Number;
+        private var sourceInvalid:Boolean;
+        private var loadFailed:Boolean;
+
+        //----------------------------------
+        //  bitmapData
+        //----------------------------------
+
+        private var _bitmapData:BitmapData;
+
+        /**
+         *  Returns a copy of the BitmapData object representing
+         *  the currently loaded image content (unscaled).  This property
+         *  is null for untrusted cross domain content.
+         *
+         *  @default null
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.5
+         */
+        public function get bitmapData():BitmapData
+        {
+            return _bitmapData ? _bitmapData.clone() : _bitmapData;
+        }
+
+        //----------------------------------
+        //  bytesLoaded
+        //----------------------------------
+
+        private var _bytesLoaded:Number = NaN;
+
+        /**
+         *  The number of bytes of the image already loaded.
+         *  Only relevant for images loaded by request URL.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.5
+         */
+        public function get bytesLoaded():Number
+        {
+            return _bytesLoaded;
+        }
+
+        //----------------------------------
+        //  bytesTotal
+        //----------------------------------
+
+        private var _bytesTotal:Number = NaN;
+
+        /**
+         *  The total image data in bytes loaded or pending load.
+         *  Only relevant for images loaded by request URL.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.5
+         */
+        public function get bytesTotal():Number
+        {
+            return _bytesTotal;
+        }
+
+        //----------------------------------
+        //  clearOnLoad
+        //----------------------------------
+
+        private var _clearOnLoad:Boolean = true;
+
+        /**
+         *  Denotes whether or not to clear previous
+         *  image content prior to loading new content.
+         *
+         *  @default true
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.5
+         */
+        public function get clearOnLoad():Boolean
+        {
+            return _clearOnLoad;
+        }
+
+        /**
+         *  @private
+         */
+        public function set clearOnLoad(value:Boolean):void
+        {
+            _clearOnLoad = value;
+        }
+
+        //----------------------------------
+        //  contentLoaderGrouping
+        //----------------------------------
+
+        private var _contentLoaderGrouping:String;
+
+        /**
+         *  Optional content grouping identifier to pass to the an
+         *  associated IContentLoader instance's load() method.
+         *  This property is only considered when a valid contentLoader
+         *  is assigned.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get contentLoaderGrouping():String
+        {
+            return _contentLoaderGrouping;
+        }
+
+        /**
+         *  @private
+         */
+        public function set contentLoaderGrouping(value:String):void
+        {
+            if (value != _contentLoaderGrouping)
+            {
+                _contentLoaderGrouping = value;
+                invalidateProperties();
+            }
+        }
+
+        //----------------------------------
+        //  contentLoader
+        //----------------------------------
+
+        private var _contentLoader:IContentLoader;
+        private var contentLoaderInvalid:Boolean;
+
+        /**
+         *  Optional custom image loader (e.g. image cache or queue) to
+         *  associate with content loader client.
+         *
+         *  @default null
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get contentLoader():IContentLoader
+        {
+            return _contentLoader;
+        }
+
+        /**
+         *  @private
+         */
+        public function set contentLoader(value:IContentLoader):void
+        {
+            if (value != _contentLoader)
+            {
+                _contentLoader = value;
+                contentLoaderInvalid = true;
+                invalidateProperties();
+            }
+        }
+
+        //----------------------------------
+        //  fillMode
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        protected var _fillMode:String = BitmapFillMode.SCALE;
+
+        [Inspectable(category="General", enumeration="clip,repeat,scale", defaultValue="scale")]
+
+        /**
+         *  The fillMode determines how the bitmap fills in the dimensions. If you set the value
+         *  of this property in a tag, use the string (such as "repeat"). If you set the value of
+         *  this property in ActionScript, use the constant (such as BitmapFillMode.CLIP).
+         *
+         *  When set to BitmapFillMode.CLIP ("clip"), the bitmap
+         *  ends at the edge of the region.
+         *
+         *  When set to BitmapFillMode.REPEAT ("repeat"), the bitmap
+         *  repeats to fill the region.
+         *
+         *  When set to BitmapFillMode.SCALE ("scale"), the bitmap
+         *  stretches to fill the region.
+         *
+         *  @default BitmapFillMode.SCALE
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        public function get fillMode():String
+        {
+            return _fillMode;
+        }
+
+        /**
+         *  @private
+         */
+        public function set fillMode(value:String):void
+        {
+            if (value != _fillMode)
+            {
+                _fillMode = value;
+                invalidateDisplayList();
+            }
+        }
+
+        //----------------------------------
+        //  horizontalAlign
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        private var _horizontalAlign:String = HorizontalAlign.CENTER;
+
+        [Inspectable(category="General", enumeration="left,right,center", defaultValue="center")]
+
+        /**
+         *  The horizontal alignment of the content when it does not have
+         *  a one-to-one aspect ratio and scaleMode is set to
+         *  BitmapScaleMode.LETTERBOX.
+         *
+         *
Can be one of HorizontalAlign.LEFT ("left"),
+         *  HorizontalAlign.RIGHT ("right"), or
+         *  HorizontalAlign.CENTER ("center").

+         *
+         *
This property is only applicable when fillMode is set to
+         *  to BitmapFillMode.SCALE ("scale").

+         *
+         *  @default HorizontalAlign.CENTER
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        public function get horizontalAlign():String
+        {
+            return _horizontalAlign;
+        }
+
+        /**
+         *  @private
+         */
+        public function set horizontalAlign(value:String):void
+        {
+            if (value == _horizontalAlign)
+                return;
+
+            _horizontalAlign = value;
             invalidateDisplayList();
         }
-    }
-
-    /**
-     *  @private
-     */
-    public function get smooth():Boolean
-    {
-        return _smooth;
-    }
-
-    //----------------------------------
-    //  smoothingQuality
-    //----------------------------------
-
-    private var _smoothingQuality:String = BitmapSmoothingQuality.DEFAULT;
-
-    [Inspectable(category="General", enumeration="default,high", defaultValue="default")]
-
-    /**
-     *  Determines how the image is down-scaled.  When set to
-     *  BitmapSmoothingQuality.BEST, the image is resampled (if data
-     *  is from a trusted source) to achieve a higher quality result.
-     *  If set to BitmapSmoothingQuality.DEFAULT, the default stage
-     *  quality for scaled bitmap fills is used.
-     *
-     *  @default BitmapSmoothingQuality.DEFAULT
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function set smoothingQuality(value:String):void
-    {
-        if (value != _smoothingQuality)
-        {
-            _smoothingQuality = value;
+
+        /**
+         *  @private
+         */
+        private function getHorizontalAlignValue():Number
+        {
+            if (_horizontalAlign == HorizontalAlign.LEFT)
+                return 0;
+            else if (_horizontalAlign == HorizontalAlign.RIGHT)
+                return 1;
+            else
+                return 0.5;
+        }
+
+        //----------------------------------
+        //  preliminaryHeight
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        private var _preliminaryHeight:Number = NaN;
+
+        /**
+         *  Provides an estimate to use for height when the "measured" bounds
+         *  of the image is requested by layout, but the image data has
+         *  yet to complete loading. When NaN the measured height is 0 until
+         *  the image has finished loading.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get preliminaryHeight():Number
+        {
+            return _preliminaryHeight;
+        }
+
+        /**
+         *  @private
+         */
+        public function set preliminaryHeight(value:Number):void
+        {
+            if (value != _preliminaryHeight)
+            {
+                _preliminaryHeight = value;
+                invalidateSize();
+            }
+        }
+
+        //----------------------------------
+        //  preliminaryWidth
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        private var _preliminaryWidth:Number = NaN;
+
+        /**
+         *  Provides an estimate to use for width when the "measured" bounds
+         *  of the image is requested by layout, but the image data has
+         *  yet to complete loading. When NaN the measured width is 0 until
+         *  the image has finished loading.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get preliminaryWidth():Number
+        {
+            return _preliminaryWidth;
+        }
+
+        /**
+         *  @private
+         */
+        public function set preliminaryWidth(value:Number):void
+        {
+            if (value != _preliminaryWidth)
+            {
+                _preliminaryWidth = value;
+                invalidateSize();
+            }
+        }
+
+        //----------------------------------
+        //  scaleMode
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        private var _scaleMode:String = BitmapScaleMode.STRETCH;
+
+        [Inspectable(category="General", enumeration="stretch,letterbox", defaultValue="stretch")]
+
+        /**
+         *  Determines how the image is scaled when fillMode is set to
+         *  BitmapFillMode.SCALE.
+         *
+         *
When set to BitmapScaleMode.STRETCH ("stretch"),
+         *  the image is stretched to fit.

+         *
+         *
When set to BitmapScaleMode.LETTERBOX ("letterbox"),
+         *  the image is scaled with respect to the original unscaled image's
+         *  aspect ratio.

+         *
+         *  @default BitmapScaleMode.STRETCH
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10.1
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.5
+         */
+        public function get scaleMode():String
+        {
+            return _scaleMode;
+        }
+
+        /**
+         *  @private
+         */
+        public function set scaleMode(value:String):void
+        {
+            if (value == _scaleMode)
+                return;
+
+            _scaleMode = value;
             invalidateDisplayList();
         }
-    }
-
-    /**
-     *  @private
-     */
-    public function get smoothingQuality():String
-    {
-        return _smoothingQuality;
-    }
-
-    //----------------------------------
-    //  source
-    //----------------------------------
-
-    private var _source:Object;
-
-    [Bindable("sourceChanged")]
-    [Inspectable(category="General")]
-
-    /**
-     *  The source used for the bitmap fill. The fill can render from various
-     *  graphical sources, including the following:
-     *

-     *
A Bitmap or BitmapData instance.

-     *
A class representing a subclass of DisplayObject. The BitmapFill
-     *       instantiates the class and creates a bitmap rendering of it.

-     *
An instance of a DisplayObject. The BitmapFill copies it into a
-     *       Bitmap for filling.

-     *
The name of an external image file.

-     *

-     *
-     *
If you use an image file for the source, it can be of type PNG, GIF,
-     *  or JPG.

-     *
-     *
To specify an embedded image source, you can use the @Embed directive,
-     *  as the following example shows:
-     *

-     *  source="@Embed('<i>image_location</i>')"
-     *

-     *

-     *
-     *
The image location can be specified via a URL, URLRequest, or file
-     *  reference. If it is a file reference, its location is relative to the
-     *  location of the file that is being compiled.

-     *
-     *
The BitmapImage class is designed to work with embedded images or
-     *  images that are loaded at run time.

-     *
-     *
If the source is a Bitmap or BitmapData instance or is an external
-     *  image file, it is the responsibility of the caller to dispose of the
-     *  source once it is no longer needed. If ImageLoader created the BitmapData
-     *  instance, then it will dispose of the BitmapData once the source has
-     *  changed.

-     *
-     *  @see flash.display.Bitmap
-     *  @see flash.display.BitmapData
-     *  @see mx.graphics.BitmapFill
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    public function get source():Object
-    {
-        return _source;
-    }
-
-    /**
-     *  @private
-     */
-    public function set source(value:Object):void
-    {
-        if (value != _source)
-        {
-            // Remove listeners from any previous load instance and clear
-            // our reference to any existing load-event dispatcher. This ensures
-            // for example that we do not receive further load related events
-            // our previous content before we can consider the new source.
-            clearLoadingContent();
-
-            _source = value;
-            sourceInvalid = true;
-            loadFailed = false;
-            invalidateProperties();
-            dispatchEvent(new Event("sourceChanged"));
-        }
-    }
-
-    //----------------------------------
-    //  sourceHeight
-    //----------------------------------
-
-    /**
-     *  Provides the unscaled height of the original image data.
-     *
-     *  @default NaN
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get sourceHeight():Number
-    {
-        return imageHeight;
-    }
-
-    //----------------------------------
-    //  sourceWidth
-    //----------------------------------
-
-    /**
-     *  Provides the unscaled width of the original image data.
-     *
-     *  @default NaN
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get sourceWidth():Number
-    {
-        return imageWidth;
-    }
-
-    //----------------------------------
-    //  trustedSource
-    //----------------------------------
-
-    private var _trustedSource:Boolean = true;
-
-    /**
-     *  A read-only flag denoting whether the currently loaded
-     *  content is considered loaded form a source whose security
-     *  policy allows for cross domain image access.  When false,
-     *  advanced bitmap operations such as high quality scaling,
-     *  tiling, etc. are not permitted.  This flag is set once an
-     *  image has been fully loaded.
-     *
-     *  @default true
-     *
-     *  @langversion 4.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get trustedSource():Boolean
-    {
-        return _trustedSource;
-    }
-
-    //----------------------------------
-    //  verticalAlign
-    //----------------------------------
-
-    /**
-     *  @private
-     */
-    private var _verticalAlign:String = VerticalAlign.MIDDLE;
-
-    [Inspectable(category="General", enumeration="top,bottom,middle", defaultValue="middle")]
-
-    /**
-     *  The vertical alignment of the content when it does not have
-     *  a one-to-one aspect ratio and scaleMode is set to
-     *  BitmapScaleMode.LETTERBOX.
-     *
-     *
Can be one of VerticalAlign.TOP ("top"),
-     *  VerticalAlign.BOTTOM ("bottom"), or
-     *  VerticalAlign.MIDDLE ("middle").

-     *
-     *
This property is only applicable when scaleMode is set to
-     *  to BitmapFillMode.SCALE ("scale").

-     *
-     *  @default VerticalAlign.MIDDLE
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4.5
-     */
-    public function get verticalAlign():String
-    {
-        return _verticalAlign;
-    }
-
-    /**
-     *  @private
-     */
-    public function set verticalAlign(value:String):void
-    {
-        if (value == _verticalAlign)
-            return;
-
-        _verticalAlign = value;
-        invalidateDisplayList();
-    }
-
-    /**
-     *  @private
-     */
-    private function getVerticalAlignValue():Number
-    {
-        if (_verticalAlign == VerticalAlign.TOP)
-            return 0;
-        else if (_verticalAlign == VerticalAlign.BOTTOM)
-            return 1;
-        else
-            return 0.5;
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    //  GraphicElement Overrides
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     *  @inheritDoc
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    override protected function commitProperties():void
-    {
-        validateSource();
-        super.commitProperties();
-    }
-
-    /**
-     *  @inheritDoc
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    override protected function measure():void
-    {
-        if (loadedContent)
-        {
-            // Return size of our loaded image content.
-            measuredWidth = imageWidth;
-            measuredHeight = imageHeight;
+
+        //----------------------------------
+        //  smooth
+        //----------------------------------
+
+        private var _smooth:Boolean = false;
+
+        [Inspectable(category="General", enumeration="true,false", defaultValue="false")]
+
+        /**
+         *  @copy flash.display.GraphicsBitmapFill#smooth
+         *
+         *  @default false
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        public function set smooth(value:Boolean):void
+        {
+            if (value != _smooth)
+            {
+                _smooth = value;
+                invalidateDisplayList();
+            }
+        }
+
+        /**
+         *  @private
+         */
+        public function get smooth():Boolean
+        {
+            return _smooth;
         }
-        else if (_bitmapData)
-        {
-            // Return size of our bitmap data.
-            measuredWidth = _bitmapData.width;
-            measuredHeight = _bitmapData.height;
-        }
-        else
-        {
-            // If we are loading new content we keep the old measured width/height to avoid
-            // sizing to 0,0 for a frame unnecessarily. Otherwise we fall back to 0 unless
-            // a preliminaryWidth/Height is set.
-            var usePreviousSize:Boolean = !(_source == null || _source == "" || loadFailed);
-            var previousWidth:Number = usePreviousSize ? measuredWidth : 0;
-            var previousHeight:Number = usePreviousSize ? measuredHeight : 0;
-
-            measuredWidth = !isNaN(_preliminaryWidth) && (previousWidth == 0) ?
-                _preliminaryWidth : previousWidth;
-            measuredHeight = !isNaN(_preliminaryHeight) && (previousHeight == 0) ?
-                _preliminaryHeight : previousHeight;
-
-            return;
-        }
-
-        // Consider aspectRatio
-        if (maintainAspectRatio && measuredWidth > 0 && measuredHeight > 0)
-        {
-            if(!isNaN(explicitWidth) && isNaN(explicitHeight) &&
-                isNaN(percentHeight))
-            {
-                measuredHeight = explicitWidth/measuredWidth * measuredHeight;
-            }
-            else if (!isNaN(explicitHeight) && isNaN(explicitWidth) &&
-                isNaN(percentWidth))
-            {
-                measuredWidth = explicitHeight/measuredHeight * measuredWidth;
-            }
-            else if (!isNaN(percentWidth) && isNaN(explicitHeight) &&
-                isNaN(percentHeight) && width > 0)
-            {
-                measuredHeight = width/measuredWidth * measuredHeight;
-            }
-            else if (!isNaN(percentHeight) && isNaN(explicitWidth) &&
-                isNaN(percentWidth) && height > 0)
-            {
-                measuredWidth = height/measuredHeight * measuredWidth;
-            }
-        }
-    }
-
-    /**
-     *  @inheritDoc
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    override protected function updateDisplayList(unscaledWidth:Number,
-                                                  unscaledHeight:Number):void
-    {
-        super.updateDisplayList(unscaledWidth, unscaledHeight);
-
-        var adjustedHeight:Number = unscaledHeight;
-        var adjustedWidth:Number = unscaledWidth;
-
-        // Consider aspectRatio
-        if (maintainAspectRatio)
-        {
-            var aspectRatio:Number = unscaledWidth/unscaledHeight;
-            var imageAspectRatio:Number = imageWidth/imageHeight;
-            if (!isNaN(imageAspectRatio))
-            {
-                if (imageAspectRatio > aspectRatio)
-                    adjustedHeight = unscaledWidth / imageAspectRatio;
-                else
-                    adjustedWidth = unscaledHeight * imageAspectRatio;
-
-                if ((!isNaN(percentWidth) && isNaN(percentHeight) && isNaN(explicitHeight)) ||
-                    (!isNaN(percentHeight) && isNaN(percentWidth) && isNaN(explicitWidth)))
-                {
-                    if (aspectRatio != imageAspectRatio)
+
+        //----------------------------------
+        //  smoothingQuality
+        //----------------------------------
+
+        private var _smoothingQuality:String = BitmapSmoothingQuality.DEFAULT;
+
+        [Inspectable(category="General", enumeration="default,high", defaultValue="default")]
+
+        /**
+         *  Determines how the image is down-scaled.  When set to
+         *  BitmapSmoothingQuality.BEST, the image is resampled (if data
+         *  is from a trusted source) to achieve a higher quality result.
+         *  If set to BitmapSmoothingQuality.DEFAULT, the default stage
+         *  quality for scaled bitmap fills is used.
+         *
+         *  @default BitmapSmoothingQuality.DEFAULT
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function set smoothingQuality(value:String):void
+        {
+            if (value != _smoothingQuality)
+            {
+                _smoothingQuality = value;
+                invalidateDisplayList();
+            }
+        }
+
+        /**
+         *  @private
+         */
+        public function get smoothingQuality():String
+        {
+            return _smoothingQuality;
+        }
+
+        //----------------------------------
+        //  source
+        //----------------------------------
+
+        private var _source:Object;
+
+        [Bindable("sourceChanged")]
+        [Inspectable(category="General")]
+
+        /**
+         *  The source used for the bitmap fill. The fill can render from various
+         *  graphical sources, including the following:
+         *

+         *
A Bitmap or BitmapData instance.

+         *
A class representing a subclass of DisplayObject. The BitmapFill
+         *       instantiates the class and creates a bitmap rendering of it.

+         *
An instance of a DisplayObject. The BitmapFill copies it into a
+         *       Bitmap for filling.

+         *
The name of an external image file.

+         *

+         *
+         *
If you use an image file for the source, it can be of type PNG, GIF,
+         *  or JPG.

+         *
+         *
To specify an embedded image source, you can use the @Embed directive,
+         *  as the following example shows:
+         *

+         *  source="@Embed('<i>image_location</i>')"
+         *

+         *

+         *
+         *
The image location can be specified via a URL, URLRequest, or file
+         *  reference. If it is a file reference, its location is relative to the
+         *  location of the file that is being compiled.

+         *
+         *
The BitmapImage class is designed to work with embedded images or
+         *  images that are loaded at run time.

+         *
+         *
If the source is a Bitmap or BitmapData instance or is an external
+         *  image file, it is the responsibility of the caller to dispose of the
+         *  source once it is no longer needed. If ImageLoader created the BitmapData
+         *  instance, then it will dispose of the BitmapData once the source has
+         *  changed.

+         *
+         *  @see flash.display.Bitmap
+         *  @see flash.display.BitmapData
+         *  @see mx.graphics.BitmapFill
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        public function get source():Object
+        {
+            return _source;
+        }
+
+        /**
+         *  @private
+         */
+        public function set source(value:Object):void
+        {
+            if (value != _source)
+            {
+                // Remove listeners from any previous load instance and clear
+                // our reference to any existing load-event dispatcher. This ensures
+                // for example that we do not receive further load related events
+                // our previous content before we can consider the new source.
+                clearLoadingContent();
+
+                // Remove any event listeners from previous source.
+                removeAddedToStageHandler(_source);
+
+                _source = value;
+                sourceInvalid = true;
+                loadFailed = false;
+                invalidateProperties();
+                dispatchEvent(new Event("sourceChanged"));
+            }
+        }
+
+        //----------------------------------
+        //  sourceHeight
+        //----------------------------------
+
+        /**
+         *  Provides the unscaled height of the original image data.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get sourceHeight():Number
+        {
+            return imageHeight;
+        }
+
+        //----------------------------------
+        //  sourceWidth
+        //----------------------------------
+
+        /**
+         *  Provides the unscaled width of the original image data.
+         *
+         *  @default NaN
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get sourceWidth():Number
+        {
+            return imageWidth;
+        }
+
+        //----------------------------------
+        //  trustedSource
+        //----------------------------------
+
+        private var _trustedSource:Boolean = true;
+
+        /**
+         *  A read-only flag denoting whether the currently loaded
+         *  content is considered loaded form a source whose security
+         *  policy allows for cross domain image access.  When false,
+         *  advanced bitmap operations such as high quality scaling,
+         *  tiling, etc. are not permitted.  This flag is set once an
+         *  image has been fully loaded.
+         *
+         *  @default true
+         *
+         *  @langversion 4.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get trustedSource():Boolean
+        {
+            return _trustedSource;
+        }
+
+        //----------------------------------
+        //  verticalAlign
+        //----------------------------------
+
+        /**
+         *  @private
+         */
+        private var _verticalAlign:String = VerticalAlign.MIDDLE;
+
+        [Inspectable(category="General", enumeration="top,bottom,middle", defaultValue="middle")]
+
+        /**
+         *  The vertical alignment of the content when it does not have
+         *  a one-to-one aspect ratio and scaleMode is set to
+         *  BitmapScaleMode.LETTERBOX.
+         *
+         *
Can be one of VerticalAlign.TOP ("top"),
+         *  VerticalAlign.BOTTOM ("bottom"), or
+         *  VerticalAlign.MIDDLE ("middle").

+         *
+         *
This property is only applicable when scaleMode is set to
+         *  to BitmapFillMode.SCALE ("scale").

+         *
+         *  @default VerticalAlign.MIDDLE
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4.5
+         */
+        public function get verticalAlign():String
+        {
+            return _verticalAlign;
+        }
+
+        /**
+         *  @private
+         */
+        public function set verticalAlign(value:String):void
+        {
+            if (value == _verticalAlign)
+                return;
+
+            _verticalAlign = value;
+            invalidateDisplayList();
+        }
+
+        /**
+         *  @private
+         */
+        private function getVerticalAlignValue():Number
+        {
+            if (_verticalAlign == VerticalAlign.TOP)
+                return 0;
+            else if (_verticalAlign == VerticalAlign.BOTTOM)
+                return 1;
+            else
+                return 0.5;
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  GraphicElement Overrides
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  @inheritDoc
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        override protected function commitProperties():void
+        {
+            validateSource();
+            super.commitProperties();
+        }
+
+        /**
+         *  @inheritDoc
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        override protected function measure():void
+        {
+            if (loadedContent)
+            {
+                // Return size of our loaded image content.
+                measuredWidth = imageWidth;
+                measuredHeight = imageHeight;
+            }
+            else if (_bitmapData)
+            {
+                // Return size of our bitmap data.
+                measuredWidth = _bitmapData.width;
+                measuredHeight = _bitmapData.height;
+            }
+            else
+            {
+                // If we are loading new content we keep the old measured width/height to avoid
+                // sizing to 0,0 for a frame unnecessarily. Otherwise we fall back to 0 unless
+                // a preliminaryWidth/Height is set.
+                var usePreviousSize:Boolean = !(_source == null || _source == "" || loadFailed);
+                var previousWidth:Number = usePreviousSize ? measuredWidth : 0;
+                var previousHeight:Number = usePreviousSize ? measuredHeight : 0;
+
+                measuredWidth = !isNaN(_preliminaryWidth) && (previousWidth == 0) ?
+                    _preliminaryWidth : previousWidth;
+                measuredHeight = !isNaN(_preliminaryHeight) && (previousHeight == 0) ?
+                    _preliminaryHeight : previousHeight;
+
+                return;
+            }
+
+            // Consider aspectRatio
+            if (maintainAspectRatio && measuredWidth > 0 && measuredHeight > 0)
+            {
+                if(!isNaN(explicitWidth) && isNaN(explicitHeight) &&
+                    isNaN(percentHeight))
+                {
+                    measuredHeight = explicitWidth/measuredWidth * measuredHeight;
+                }
+                else if (!isNaN(explicitHeight) && isNaN(explicitWidth) &&
+                    isNaN(percentWidth))
+                {
+                    measuredWidth = explicitHeight/measuredHeight * measuredWidth;
+                }
+                else if (!isNaN(percentWidth) && isNaN(explicitHeight) &&
+                    isNaN(percentHeight) && width > 0)
+                {
+                    measuredHeight = width/measuredWidth * measuredHeight;
+                }
+                else if (!isNaN(percentHeight) && isNaN(explicitWidth) &&
+                    isNaN(percentWidth) && height > 0)
+                {
+                    measuredWidth = height/measuredHeight * measuredWidth;
+                }
+            }
+        }
+
+        /**
+         *  @inheritDoc
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 1.5
+         *  @productversion Flex 4
+         */
+        override protected function updateDisplayList(unscaledWidth:Number,
+                                                      unscaledHeight:Number):void
+        {
+            super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+            var adjustedHeight:Number = unscaledHeight;
+            var adjustedWidth:Number = unscaledWidth;
+
+            // Consider aspectRatio
+            if (maintainAspectRatio)
+            {
+                var aspectRatio:Number = unscaledWidth/unscaledHeight;
+                var imageAspectRatio:Number = imageWidth/imageHeight;
+                if (!isNaN(imageAspectRatio))
+                {
+                    if (imageAspectRatio > aspectRatio)
+                        adjustedHeight = unscaledWidth / imageAspectRatio;
+                    else
+                        adjustedWidth = unscaledHeight * imageAspectRatio;
+
+                    if ((!isNaN(percentWidth) && isNaN(percentHeight) && isNaN(explicitHeight)) ||
+                        (!isNaN(percentHeight) && isNaN(percentWidth) && isNaN(explicitWidth)))
                     {
-                        invalidateSize();
-                        return;
+                        if (aspectRatio != imageAspectRatio)
+                        {
+                            invalidateSize();
+                            return;
+                        }
                     }
                 }
-            }
-        }
-
-        if (!_bitmapData || !drawnDisplayObject || !(drawnDisplayObject is Sprite))
-        {
-            if (loadedContent)
-            {
-                // We are hosting a display object so let's scale, align, and clip
-                // as necessary.
-
-                if (_fillMode == BitmapFillMode.SCALE)
-                {
-                    loadedContent.width = adjustedWidth;
-                    loadedContent.height = adjustedHeight;
-                }
-
-                loadedContent.y = loadedContent.x = 0;
-
-                // Align our loaded content as necessary if our width
+            }
+
+            if (!_bitmapData || !drawnDisplayObject || !(drawnDisplayObject is Sprite))
+            {
+                if (loadedContent)
+                {
+                    // We are hosting a display object so let's scale, align, and clip
+                    // as necessary.
+
+                    if (_fillMode == BitmapFillMode.SCALE)
+                    {
+                        loadedContent.width = adjustedWidth;
+                        loadedContent.height = adjustedHeight;
+                    }
+
+                    loadedContent.y = loadedContent.x = 0;
+
+                    // Align our loaded content as necessary if our width
+                    // and/or height is larger than our content height.
+                    if (maintainAspectRatio || _fillMode == BitmapFillMode.CLIP)
+                    {
+                        var contentWidth:Number = (_fillMode == BitmapFillMode.CLIP) ?
+                            imageWidth : adjustedWidth;
+                        var contentHeight:Number = (_fillMode == BitmapFillMode.CLIP) ?
+                            imageHeight : adjustedHeight;
+
+                        if (unscaledHeight > contentHeight)
+                            loadedContent.y = Math.floor((unscaledHeight - contentHeight)
+                                * getVerticalAlignValue());
+
+                        if (unscaledWidth > contentWidth)
+                            loadedContent.x = Math.floor((unscaledWidth - contentWidth)
+                                * getHorizontalAlignValue());
+                    }
+
+                    // Setup clip rect if appropriate.
+                    loadedContent.scrollRect = (_fillMode == BitmapFillMode.CLIP) ?
+                        new Rectangle(0, 0, unscaledWidth, unscaledHeight) : null;
+
+                }
+                return;
+            }
+
+            // The base GraphicElement class has cleared the graphics for us.
+            var g:Graphics = Sprite(drawnDisplayObject).graphics;
+
+            g.lineStyle();
+            var repeatBitmap:Boolean = false;
+            var fillScaleX:Number = 1;
+            var fillScaleY:Number = 1;
+            var roundedDrawX:Number = Math.round(drawX);
+            var roundedDrawY:Number = Math.round(drawY);
+            var fillWidth:Number = adjustedWidth;
+            var fillHeight:Number = adjustedHeight;
+
+            switch(_fillMode)
+            {
+                case BitmapFillMode.REPEAT:
+                    if (_bitmapData)
+                    {
+                        repeatBitmap = true;
+                    }
+                    break;
+
+                case BitmapFillMode.SCALE:
+                    if (_bitmapData)
+                    {
+                        fillScaleX = adjustedWidth / _bitmapData.width;
+                        fillScaleY = adjustedHeight / _bitmapData.height;
+                    }
+                    break;
+
+                case BitmapFillMode.CLIP:
+                    if (_bitmapData)
+                    {
+                        fillWidth = Math.min(adjustedWidth, _bitmapData.width);
+                        fillHeight = Math.min(adjustedHeight, _bitmapData.height);
+                    }
+                    break;
+            }
+
+            // If no scaleGrid is defined or if fillMode != SCALE, just draw
+            // the entire rect
+            if (_fillMode != BitmapFillMode.SCALE ||
+                isNaN(_scaleGridTop) ||
+                isNaN(_scaleGridBottom) ||
+                isNaN(_scaleGridLeft) ||
+                isNaN(_scaleGridRight))
+            {
+                var sampledScale:Boolean = _smooth &&
+                    (_smoothingQuality == BitmapSmoothingQuality.HIGH) &&
+                    (_fillMode == BitmapFillMode.SCALE);
+
+                var b:BitmapData = sampledScale ? resample(_bitmapData, fillWidth, fillHeight) : _bitmapData;
+
+                if (sampledScale && _fillMode == BitmapFillMode.SCALE)
+                {
+                    fillScaleX = adjustedWidth / b.width;
+                    fillScaleY = adjustedHeight / b.height;
+                }
+
+                var offsetX:Number = 0;
+                var offsetY:Number = 0;
+
+                // Align our bitmap content as necessary if our width
                 // and/or height is larger than our content height.
                 if (maintainAspectRatio || _fillMode == BitmapFillMode.CLIP)
                 {
-                    var contentWidth:Number = (_fillMode == BitmapFillMode.CLIP) ?
-                        imageWidth : adjustedWidth;
-                    var contentHeight:Number = (_fillMode == BitmapFillMode.CLIP) ?
-                        imageHeight : adjustedHeight;
+                    var cHeight:Number = b.height * fillScaleX;
+                    var cWidth:Number = b.width * fillScaleY;

-                    if (unscaledHeight > contentHeight)
-                        loadedContent.y = Math.floor((unscaledHeight - contentHeight)
+                    if (unscaledHeight > cHeight)
+                        roundedDrawY = roundedDrawY + Math.floor((unscaledHeight - cHeight)
                             * getVerticalAlignValue());
-
-                    if (unscaledWidth > contentWidth)
-                        loadedContent.x = Math.floor((unscaledWidth - contentWidth)
+
+                    if (unscaledWidth > cWidth)
+                        roundedDrawX = roundedDrawX + Math.floor((unscaledWidth - cWidth)
                             * getHorizontalAlignValue());
+                }
+
+                matrix.identity();
+                if (!(sampledScale && maintainAspectRatio))
+                    matrix.scale(fillScaleX, fillScaleY);
+                matrix.translate(roundedDrawX, roundedDrawY);
+                g.beginBitmapFill(b, matrix, repeatBitmap, _smooth);
+                g.drawRect(roundedDrawX, roundedDrawY, fillWidth, fillHeight);
+                g.endFill();
+            }
+            else
+            {
+                // If we have scaleGrid, we draw 9 sections, each with a different scale factor based
+                // on the grid region.
+
+                if (cachedSourceGrid == null)
+                {
+                    // Generate the 16 points of the source (unscaled) grid
+                    cachedSourceGrid = [];
+                    cachedSourceGrid.push([new Point(0, 0), new Point(_scaleGridLeft, 0),
+                        new Point(_scaleGridRight, 0), new Point(_bitmapData.width, 0)]);
+                    cachedSourceGrid.push([new Point(0, _scaleGridTop), new Point(_scaleGridLeft, _scaleGridTop),
+                        new Point(_scaleGridRight, _scaleGridTop), new Point(_bitmapData.width, _scaleGridTop)]);
+                    cachedSourceGrid.push([new Point(0, _scaleGridBottom), new Point(_scaleGridLeft, _scaleGridBottom),
+                        new Point(_scaleGridRight, _scaleGridBottom), new Point(_bitmapData.width, _scaleGridBottom)]);
+                    cachedSourceGrid.push([new Point(0, _bitmapData.height), new Point(_scaleGridLeft, _bitmapData.height),
+                        new Point(_scaleGridRight, _bitmapData.height), new Point(_bitmapData.width, _bitmapData.height)]);
+                }
+
+                if (cachedDestGrid == null ||
+                    previousUnscaledWidth != unscaledWidth ||
+                    previousUnscaledHeight != unscaledHeight)
+                {
+                    // Generate teh 16 points of the destination (scaled) grid
+                    var destScaleGridBottom:Number = unscaledHeight - (_bitmapData.height - _scaleGridBottom);
+                    var destScaleGridRight:Number = unscaledWidth - (_bitmapData.width - _scaleGridRight);
+                    cachedDestGrid = [];
+                    cachedDestGrid.push([new Point(0, 0), new Point(_scaleGridLeft, 0),
+                        new Point(destScaleGridRight, 0), new Point(unscaledWidth, 0)]);
+                    cachedDestGrid.push([new Point(0, _scaleGridTop), new Point(_scaleGridLeft, _scaleGridTop),
+                        new Point(destScaleGridRight, _scaleGridTop), new Point(unscaledWidth, _scaleGridTop)]);
+                    cachedDestGrid.push([new Point(0, destScaleGridBottom), new Point(_scaleGridLeft, destScaleGridBottom),
+                        new Point(destScaleGridRight, destScaleGridBottom), new Point(unscaledWidth, destScaleGridBottom)]);
+                    cachedDestGrid.push([new Point(0, unscaledHeight), new Point(_scaleGridLeft, unscaledHeight),
+                        new Point(destScaleGridRight, unscaledHeight), new Point(unscaledWidth, unscaledHeight)]);
+                }
+
+                var sourceSection:Rectangle = new Rectangle();
+                var destSection:Rectangle = new Rectangle();
+
+                // Iterate over the columns and rows. We draw each of the nine sections at a calculated
+                // scale and translation.
+                for (var rowIndex:int=0; rowIndex < 3; rowIndex++)
+                {
+                    for (var colIndex:int = 0; colIndex < 3; colIndex++)
+                    {
+                        // Create the source and destination rectangles for the current section
+                        sourceSection.topLeft = cachedSourceGrid[rowIndex][colIndex];
+                        sourceSection.bottomRight = cachedSourceGrid[rowIndex+1][colIndex+1];
+
+                        destSection.topLeft = cachedDestGrid[rowIndex][colIndex];
+                        destSection.bottomRight = cachedDestGrid[rowIndex+1][colIndex+1];
+
+                        matrix.identity();
+                        // Scale the bitmap by the ratio between the source and destination dimensions
+                        matrix.scale(destSection.width / sourceSection.width, destSection.height / sourceSection.height);
+                        // Translate based on the difference between the source and destination coordinates,
+                        // making sure to account for the new scale.
+                        matrix.translate(destSection.x - sourceSection.x * matrix.a, destSection.y - sourceSection.y * matrix.d);
+                        matrix.translate(roundedDrawX, roundedDrawY);
+
+                        // Draw the bitmap for the current section
+                        g.beginBitmapFill(_bitmapData, matrix);
+                        g.drawRect(destSection.x + roundedDrawX, destSection.y + roundedDrawY, destSection.width, destSection.height);
+                        g.endFill();
+                    }
+                }
+            }
+
+            previousUnscaledWidth = unscaledWidth;
+            previousUnscaledHeight = unscaledHeight;
+        }
+
+        /**
+         *  @private
+         */
+        override protected function get needsDisplayObject():Boolean
+        {
+            // If we are hosting untrusted content the hosted loader becomes
+            // our display object.
+            return !trustedSource || super.needsDisplayObject;
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  Methods
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  @private
+         *  Utility function that sets the underlying bitmapData property.
+         */
+        protected function setBitmapData(bitmapData:BitmapData,
+                                         internallyCreated:Boolean = false):void
+        {
+            // Clear previous bitmapData
+            clearBitmapData();
+
+            // Reset imageWidth/Height, as we aren't
+            // loading external content so no reason to
+            // cache our existing image width and height.
+            imageWidth = imageHeight = NaN;
+
+            // Clear any currently loading content.
+            clearLoadingContent();
+
+            if (bitmapData)
+            {
+                bitmapDataCreated = internallyCreated;
+
+                _bitmapData = bitmapData;
+
+                imageWidth = bitmapData.width;
+                imageHeight = bitmapData.height;
+
+                // Flush the cached scale grid points
+                cachedSourceGrid = null;
+                cachedDestGrid = null;
+
+                // Dispatch ready event
+                dispatchEvent(new FlexEvent(FlexEvent.READY));
+            }
+
+            invalidateSize();
+            invalidateDisplayList();
+        }
+
+        /**
+         *  @private
+         *  Utility method which analyzes our source and either acquires the
+         *  associated bitmap data immediately or queues up a remote request
+         *  as necessary.
+         */
+        mx_internal function applySource():void
+        {
+            var value:Object = _source;
+            var bitmapData:BitmapData;
+            var tmpSprite:DisplayObject;
+
+            // Clear the previous scaleGrid properties
+            _scaleGridLeft = NaN;
+            _scaleGridRight = NaN;
+            _scaleGridTop = NaN;
+            _scaleGridBottom = NaN;
+            var currentBitmapCreated:Boolean = false;
+
+            // Reset byte counts and _trustedSource
+            _bytesLoaded = NaN;
+            _bytesTotal = NaN;
+            _trustedSource = true;
+
+            // We'll need to reconsider display object sharing.
+            invalidateDisplayObjectSharing();
+            invalidateDisplayList();
+
+            // Remove any previously hosted content prior to loading
+            // new content (if applicable).
+            if (_clearOnLoad)
+                removePreviousContent();
+
+            if (value is Class)
+            {
+                var cls:Class = Class(value);
+                value = new cls();
+                currentBitmapCreated = true;
+            }
+            else if (value is String || value is URLRequest)
+            {
+                loadExternal(value);
+            }
+            else if (value is ByteArray)
+            {
+                loadFromBytes(value as ByteArray);
+            }
+
+            if (value is BitmapData)
+            {
+                bitmapData = value as BitmapData;
+            }
+            else if (value is Bitmap)
+            {
+                bitmapData = value.bitmapData;
+            }
+            else if (value is DisplayObject)
+            {
+                tmpSprite = value as DisplayObject;
+
+                if ((tmpSprite.width == 0 || tmpSprite.height == 0) && !tmpSprite.stage )
+                {
+                    // If our source DisplayObject has yet to be assigned a stage,
+                    // and doesn't have valid bounds, it is not ready to be captured,
+                    // so we defer bitmap capture until it is added to the display list.
+                    tmpSprite.addEventListener(Event.ADDED_TO_STAGE, source_addedToStageHandler);
+                    return;
                 }
-
-                // Setup clip rect if appropriate.
-                loadedContent.scrollRect = (_fillMode == BitmapFillMode.CLIP) ?
-                    new Rectangle(0, 0, unscaledWidth, unscaledHeight) : null;
-
-            }
-            return;
-        }
-
-        // The base GraphicElement class has cleared the graphics for us.
-        var g:Graphics = Sprite(drawnDisplayObject).graphics;
-
-        g.lineStyle();
-        var repeatBitmap:Boolean = false;
-        var fillScaleX:Number = 1;
-        var fillScaleY:Number = 1;
-        var roundedDrawX:Number = Math.round(drawX);
-        var roundedDrawY:Number = Math.round(drawY);
-        var fillWidth:Number = adjustedWidth;
-        var fillHeight:Number = adjustedHeight;
-
-        switch(_fillMode)
-        {
-            case BitmapFillMode.REPEAT:
-                if (_bitmapData)
-                {
-                    repeatBitmap = true;
-                }
-                break;
-
-            case BitmapFillMode.SCALE:
-                if (_bitmapData)
-                {
-                    fillScaleX = adjustedWidth / _bitmapData.width;
-                    fillScaleY = adjustedHeight / _bitmapData.height;
-                }
-                break;
-
-            case BitmapFillMode.CLIP:
-                if (_bitmapData)
-                {
-                    fillWidth = Math.min(adjustedWidth, _bitmapData.width);
-                    fillHeight = Math.min(adjustedHeight, _bitmapData.height);
-                }
-                break;
-        }
-
-        // If no scaleGrid is defined or if fillMode != SCALE, just draw
-        // the entire rect
-        if (_fillMode != BitmapFillMode.SCALE ||
-            isNaN(_scaleGridTop) ||
-            isNaN(_scaleGridBottom) ||
-            isNaN(_scaleGridLeft) ||
-            isNaN(_scaleGridRight))
-        {
-            var sampledScale:Boolean = _smooth &&
-                (_smoothingQuality == BitmapSmoothingQuality.HIGH) &&
-                (_fillMode == BitmapFillMode.SCALE);
-
-            var b:BitmapData = sampledScale ? resample(_bitmapData, fillWidth, fillHeight) : _bitmapData;
-
-            if (sampledScale && _fillMode == BitmapFillMode.SCALE)
-            {
-                fillScaleX = adjustedWidth / b.width;
-                fillScaleY = adjustedHeight / b.height;
-            }
-
-            var offsetX:Number = 0;
-            var offsetY:Number = 0;
-
-            // Align our bitmap content as necessary if our width
-            // and/or height is larger than our content height.
-            if (maintainAspectRatio || _fillMode == BitmapFillMode.CLIP)
-            {
-                var cHeight:Number = b.height * fillScaleX;
-                var cWidth:Number = b.width * fillScaleY;
-
-                if (unscaledHeight > cHeight)
-                    roundedDrawY = roundedDrawY + Math.floor((unscaledHeight - cHeight)
-                        * getVerticalAlignValue());
-
-                if (unscaledWidth > cWidth)
-                    roundedDrawX = roundedDrawX + Math.floor((unscaledWidth - cWidth)
-                        * getHorizontalAlignValue());
-            }
-
-            matrix.identity();
-            if (!(sampledScale && maintainAspectRatio))
-                matrix.scale(fillScaleX, fillScaleY);
-            matrix.translate(roundedDrawX, roundedDrawY);
-            g.beginBitmapFill(b, matrix, repeatBitmap, _smooth);
-            g.drawRect(roundedDrawX, roundedDrawY, fillWidth, fillHeight);
-            g.endFill();
-        }
-        else
-        {
-            // If we have scaleGrid, we draw 9 sections, each with a different scale factor based
-            // on the grid region.
-
-            if (cachedSourceGrid == null)
-            {
-                // Generate the 16 points of the source (unscaled) grid
-                cachedSourceGrid = [];
-                cachedSourceGrid.push([new Point(0, 0), new Point(_scaleGridLeft, 0),
-                    new Point(_scaleGridRight, 0), new Point(_bitmapData.width, 0)]);
-                cachedSourceGrid.push([new Point(0, _scaleGridTop), new Point(_scaleGridLeft, _scaleGridTop),
-                    new Point(_scaleGridRight, _scaleGridTop), new Point(_bitmapData.width, _scaleGridTop)]);
-                cachedSourceGrid.push([new Point(0, _scaleGridBottom), new Point(_scaleGridLeft, _scaleGridBottom),
-                    new Point(_scaleGridRight, _scaleGridBottom), new Point(_bitmapData.width, _scaleGridBottom)]);
-                cachedSourceGrid.push([new Point(0, _bitmapData.height), new Point(_scaleGridLeft, _bitmapData.height),
-                    new Point(_scaleGridRight, _bitmapData.height), new Point(_bitmapData.width, _bitmapData.height)]);
-            }
-
-            if (cachedDestGrid == null ||
-                previousUnscaledWidth != unscaledWidth ||
-                previousUnscaledHeight != unscaledHeight)
-            {
-                // Generate teh 16 points of the destination (scaled) grid
-                var destScaleGridBottom:Number = unscaledHeight - (_bitmapData.height - _scaleGridBottom);
-                var destScaleGridRight:Number = unscaledWidth - (_bitmapData.width - _scaleGridRight);
-                cachedDestGrid = [];
-                cachedDestGrid.push([new Point(0, 0), new Point(_scaleGridLeft, 0),
-                    new Point(destScaleGridRight, 0), new Point(unscaledWidth, 0)]);
-                cachedDestGrid.push([new Point(0, _scaleGridTop), new Point(_scaleGridLeft, _scaleGridTop),
-                    new Point(destScaleGridRight, _scaleGridTop), new Point(unscaledWidth, _scaleGridTop)]);
-                cachedDestGrid.push([new Point(0, destScaleGridBottom), new Point(_scaleGridLeft, destScaleGridBottom),
-                    new Point(destScaleGridRight, destScaleGridBottom), new Point(unscaledWidth, destScaleGridBottom)]);
-                cachedDestGrid.push([new Point(0, unscaledHeight), new Point(_scaleGridLeft, unscaledHeight),
-                    new Point(destScaleGridRight, unscaledHeight), new Point(unscaledWidth, unscaledHeight)]);
-            }
-
-            var sourceSection:Rectangle = new Rectangle();
-            var destSection:Rectangle = new Rectangle();
-
-            // Iterate over the columns and rows. We draw each of the nine sections at a calculated
-            // scale and translation.
-            for (var rowIndex:int=0; rowIndex < 3; rowIndex++)
-            {
-                for (var colIndex:int = 0; colIndex < 3; colIndex++)
-                {
-                    // Create the source and destination rectangles for the current section
-                    sourceSection.topLeft = cachedSourceGrid[rowIndex][colIndex];
-                    sourceSection.bottomRight = cachedSourceGrid[rowIndex+1][colIndex+1];
-
-                    destSection.topLeft = cachedDestGrid[rowIndex][colIndex];
-                    destSection.bottomRight = cachedDestGrid[rowIndex+1][colIndex+1];
-
-                    matrix.identity();
-                    // Scale the bitmap by the ratio between the source and destination dimensions
-                    matrix.scale(destSection.width / sourceSection.width, destSection.height / sourceSection.height);
-                    // Translate based on the difference between the source and destination coordinates,
-                    // making sure to account for the new scale.
-                    matrix.translate(destSection.x - sourceSection.x * matrix.a, destSection.y - sourceSection.y * matrix.d);
-                    matrix.translate(roundedDrawX, roundedDrawY);
-
-                    // Draw the bitmap for the current section
-                    g.beginBitmapFill(_bitmapData, matrix);
-                    g.drawRect(destSection.x + roundedDrawX, destSection.y + roundedDrawY, destSection.width, destSection.height);
-                    g.endFill();
-                }
-            }
-        }
-
-        previousUnscaledWidth = unscaledWidth;
-        previousUnscaledHeight = unscaledHeight;
-    }
-
-    /**
-     *  @private
-     */
-    override protected function get needsDisplayObject():Boolean
-    {
-        // If we are hosting untrusted content the hosted loader becomes
-        // our display object.
-        return !trustedSource || super.needsDisplayObject;
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    //  Methods
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     *  @private
-     *  Utility function that sets the underlying bitmapData property.
-     */
-    protected function setBitmapData(bitmapData:BitmapData,
-                                     internallyCreated:Boolean = false):void
-    {
-        // Clear previous bitmapData
-        clearBitmapData();
-
-        // Reset imageWidth/Height, as we aren't
-        // loading external content so no reason to
-        // cache our existing image width and height.
-        imageWidth = imageHeight = NaN;
-
-        // Clear any currently loading content.
-        clearLoadingContent();
-
-        if (bitmapData)
-        {
-            bitmapDataCreated = internallyCreated;
-
-            _bitmapData = bitmapData;
-
-            imageWidth = bitmapData.width;
-            imageHeight = bitmapData.height;
-
-            // Flush the cached scale grid points
-            cachedSourceGrid = null;
-            cachedDestGrid = null;
-
-            // Dispatch ready event
-            dispatchEvent(new FlexEvent(FlexEvent.READY));
-        }
-
-        invalidateSize();
-        invalidateDisplayList();
-    }
-
-    /**
-     *  @private
-     *  Utility method which analyzes our source and either acquires the
-     *  associated bitmap data immediately or queues up a remote request
-     *  as necessary.
-     */
-    mx_internal function applySource():void
-    {
-        var value:Object = _source;
-        var bitmapData:BitmapData;
-        var tmpSprite:DisplayObject;
-
-        // Clear the previous scaleGrid properties
-        _scaleGridLeft = NaN;
-        _scaleGridRight = NaN;
-        _scaleGridTop = NaN;
-        _scaleGridBottom = NaN;
-        var currentBitmapCreated:Boolean = false;
-
-        // Reset byte counts and _trustedSource
-        _bytesLoaded = NaN;
-        _bytesTotal = NaN;
-        _trustedSource = true;
-
-        // We'll need to reconsider display object sharing.
-        invalidateDisplayObjectSharing();
-        invalidateDisplayList();
-
-        // Remove any previously hosted content prior to loading
-        // new content (if applicable).
-        if (_clearOnLoad)
-            removePreviousContent();
-
-        if (value is Class)
-        {
-            var cls:Class = Class(value);
-            value = new cls();
-            currentBitmapCreated = true;
-        }
-        else if (value is String || value is URLRequest)
-        {
-            loadExternal(value);
-        }
-        else if (value is ByteArray)
-        {
-            loadFromBytes(value as ByteArray);
-        }
-
-        if (value is BitmapData)
-        {
-            bitmapData = value as BitmapData;
-        }
-        else if (value is Bitmap)
-        {
-            bitmapData = value.bitmapData;
-        }
-        else if (value is DisplayObject)
-        {
-            tmpSprite = value as DisplayObject;
-        }
-        else if (value == null)
-        {
-            // This will set source to null
-        }
-        else
-        {
-            // We're loading external content or we
-            // we have an unsupported source value.
-            return;
-        }
-
-        if (!bitmapData && tmpSprite)
-        {
-            bitmapData = new BitmapData(tmpSprite.width, tmpSprite.height, true, 0);
-            bitmapData.draw(tmpSprite, new Matrix());
-            currentBitmapCreated = true;
-
-            if (tmpSprite.scale9Grid)
-            {
-                _scaleGridLeft = tmpSprite.scale9Grid.left;
-                _scaleGridRight = tmpSprite.scale9Grid.right;
-                _scaleGridTop = tmpSprite.scale9Grid.top;
-                _scaleGridBottom = tmpSprite.scale9Grid.bottom;
-            }
-        }
-
-        // Remove any previously hosted content prior to assigning
-        // new bitmap data (if we haven't already previously).
-        if (!_clearOnLoad)
-            removePreviousContent();
-
-        setBitmapData(bitmapData, currentBitmapCreated);
-    }
-
-    /**
-     *  @private
-     */
-    mx_internal function loadExternal(source:Object):void
-    {
-        if (contentLoader)
-        {
-            // We defer our load request to the configured content loader.
-            var contentRequest:ContentRequest = contentLoader.load(source, contentLoaderGrouping);
-
-            if (contentRequest.complete)
-            {
-                // No need to attach listeners as we've received a fully complete
-                // request result.
-                contentComplete(contentRequest.content);
-            }
+            }
+            else if (value == null)
+            {
+                // This will set source to null
+            }
             else
             {
-                // Attach load-event listeners to our ContentRequest instance.
-                loadingContent = contentRequest;
+                // We're loading external content or we
+                // we have an unsupported source value.
+                return;
+            }
+
+            if (!bitmapData && tmpSprite)
+            {
+                // We must ensure any IInvalidating sources
+                // are properly validated before capturing.
+                if (tmpSprite is IInvalidating)
+                    IInvalidating(tmpSprite).validateNow();
+
+                // Return immediately if our input source has 0 bounds else
+                // our BitmapData constructor will RTE.
+                if (tmpSprite.width == 0 || tmpSprite.height == 0)
+                    return;
+
+                bitmapData = new BitmapData(tmpSprite.width, tmpSprite.height, true, 0);
+                bitmapData.draw(tmpSprite, new Matrix(), tmpSprite.transform.colorTransform);
+                currentBitmapCreated = true;
+
+                if (tmpSprite.scale9Grid)
+                {
+                    _scaleGridLeft = tmpSprite.scale9Grid.left;
+                    _scaleGridRight = tmpSprite.scale9Grid.right;
+                    _scaleGridTop = tmpSprite.scale9Grid.top;
+                    _scaleGridBottom = tmpSprite.scale9Grid.bottom;
+                }
+            }
+
+            // Remove any previously hosted content prior to assigning
+            // new bitmap data (if we haven't already previously).
+            if (!_clearOnLoad)
+                removePreviousContent();
+
+            setBitmapData(bitmapData, currentBitmapCreated);
+        }
+
+        /**
+         *  @private
+         */
+        mx_internal function loadExternal(source:Object):void
+        {
+            if (contentLoader)
+            {
+                // We defer our load request to the configured content loader.
+                var contentRequest:ContentRequest = contentLoader.load(source, contentLoaderGrouping);
+
+                if (contentRequest.complete)
+                {
+                    // No need to attach listeners as we've received a fully complete
+                    // request result.
+                    contentComplete(contentRequest.content);
+                }
+                else
+                {
+                    // Attach load-event listeners to our ContentRequest instance.
+                    loadingContent = contentRequest;
+                    attachLoadingListeners();
+                }
+            }
+            else
+            {
+                var loader:Loader = new Loader();
+                var loaderContext:LoaderContext = new LoaderContext();
+
+                // Attach load-event listeners to our LoaderInfo instance.
+                loadingContent = loader.contentLoaderInfo;
                 attachLoadingListeners();
-            }
-        }
-        else
-        {
-            var loader:Loader = new Loader();
+
+                try
+                {
+                    loaderContext.checkPolicyFile = true;
+                    var urlRequest:URLRequest = source is URLRequest ?
+                        source as URLRequest : new URLRequest(source as String);
+                    loader.load(urlRequest, loaderContext);
+                }
+                catch (error:SecurityError)
+                {
+                    handleSecurityError(error);
+                }
+            }
+        }
+
+        /**
+         *  @private
+         */
+        mx_internal function loadFromBytes(source:ByteArray):void
+        {
+            var loader:Loader = new Loader();
             var loaderContext:LoaderContext = new LoaderContext();
-
-            // Attach load-event listeners to our LoaderInfo instance.
             loadingContent = loader.contentLoaderInfo;
             attachLoadingListeners();
-
+
             try
             {
-                loaderContext.checkPolicyFile = true;
-                var urlRequest:URLRequest = source is URLRequest ?
-                    source as URLRequest : new URLRequest(source as String);
-                loader.load(urlRequest, loaderContext);
+                loader.loadBytes(source as ByteArray, loaderContext);
             }
             catch (error:SecurityError)
             {
                 handleSecurityError(error);
             }
         }
-    }
-
-    /**
-     *  @private
-     */
-    mx_internal function loadFromBytes(source:ByteArray):void
-    {
-        var loader:Loader = new Loader();
-        var loaderContext:LoaderContext = new LoaderContext();
-        loadingContent = loader.contentLoaderInfo;
-        attachLoadingListeners();
-
-        try
-        {
-            loader.loadBytes(source as ByteArray, loaderContext);
-        }
-        catch (error:SecurityError)
-        {
-            handleSecurityError(error);
-        }
-    }
-
-    /**
-     * @private
-     * Utility function used for higher quality image scaling. Essentially we
-     * simply step down our bitmap size by half resulting in a much higher result
-     * though taking potentially multiple passes to accomplish.
-     */
-    protected static function resample(bitmapData:BitmapData, newWidth:uint,
-                                       newHeight:uint):BitmapData
-    {
-        var finalScale:Number = Math.max(newWidth/bitmapData.width,
-            newHeight/bitmapData.height);
-
-        var finalData:BitmapData = bitmapData;
-
-        if (finalScale > 1)
+
+        /**
+         * @private
+         * Utility function used for higher quality image scaling. Essentially we
+         * simply step down our bitmap size by half resulting in a much higher result
+         * though taking potentially multiple passes to accomplish.
+         */
+        protected static function resample(bitmapData:BitmapData, newWidth:uint,
+                                           newHeight:uint):BitmapData
+        {
+            var finalScale:Number = Math.max(newWidth/bitmapData.width,
+                newHeight/bitmapData.height);
+
+            var finalData:BitmapData = bitmapData;
+
+            if (finalScale > 1)
+            {
+                finalData = new BitmapData(bitmapData.width * finalScale,
+                    bitmapData.height * finalScale, true, 0);
+
+                finalData.draw(bitmapData, new Matrix(finalScale, 0, 0,
+                    finalScale), null, null, null, true);
+
+                return finalData;
+            }
+
+            var drop:Number = .5;
+            var initialScale:Number = finalScale;
+
+            while (initialScale/drop < 1)
+                initialScale /= drop;
+
+            var w:Number = Math.floor(bitmapData.width * initialScale);
+            var h:Number = Math.floor(bitmapData.height * initialScale);
+            var bd:BitmapData = new BitmapData(w, h, bitmapData.transparent, 0);
+
+            bd.draw(finalData, new Matrix(initialScale, 0, 0, initialScale),
+                null, null, null, true);
+            finalData = bd;
+
+            for (var scale:Number = initialScale * drop;
+                Math.round(scale * 1000) >= Math.round(finalScale * 1000);
+                scale *= drop)
+            {
+                w = Math.floor(bitmapData.width * scale);
+                h = Math.floor(bitmapData.height * scale);
+                bd = new BitmapData(w, h, bitmapData.transparent, 0);
+
+                bd.draw(finalData, new Matrix(drop, 0, 0, drop), null, null, null, true);
+                finalData.dispose();
+                finalData = bd;
+            }
+
+            return finalData;
+        }
+
+        /**
+         * @private
+         * Invoked upon completion of a load request.
+         */
+        protected function contentComplete(content:Object):void
+        {
+            if (content is LoaderInfo)
+            {
+                // Clear any previous bitmap data or loader instance.
+                setBitmapData(null);
+                removePreviousContent();
+
+                var loaderInfo:LoaderInfo = content as LoaderInfo;
+
+                if (loaderInfo.childAllowsParent)
+                {
+                    // For trusted content we adopt the loaded BitmapData.
+                    var image:Bitmap = Bitmap(loaderInfo.content);
+                    setBitmapData(image.bitmapData);
+                }
+                else
+                {
+                    // For untrusted content we must host the acquired Loader
+                    // instance directly as our DisplayObject.
+                    displayObjectSharingMode = DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT;
+                    invalidateDisplayObjectSharing();
+
+                    // Create a content holder to use as our display object.
+                    var contentHolder:Sprite = new Sprite();
+                    setDisplayObject(contentHolder);
+                    loadedContent = loaderInfo.loader;
+                    contentHolder.addChild(loadedContent);
+
+                    // Retain our source image width and height.
+                    imageWidth = loaderInfo.width;
+                    imageHeight = loaderInfo.height ;
+
+                    // Update
+                    invalidateSize();
+                    invalidateDisplayList();
+
+                    // Denote that we are hosting an untrusted image and as such some
+                    // features requiring access to the bitmap data will no longer
+                    // function.
+                    _trustedSource = false;
+
+                    // Dispatch ready event
+                    dispatchEvent(new FlexEvent(FlexEvent.READY));
+                }
+            }
+            else
+            {
+                if (content is BitmapData)
+                    setBitmapData(content as BitmapData);
+            }
+        }
+
+        /**
+         * @private
+         * Returns true if are to consider aspect ratio while scaling.
+         */
+        private function get maintainAspectRatio():Boolean
+        {
+            return (_scaleMode == BitmapScaleMode.LETTERBOX && _fillMode == BitmapFillMode.SCALE);
+        }
+
+        /**
+         * @private
+         * Removes any previously loaded content prior to loading new.
+         */
+        private function removePreviousContent():void
+        {
+            if (loadedContent && loadedContent.parent)
+            {
+                displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
+                invalidateDisplayObjectSharing();
+                loadedContent.parent.removeChild(loadedContent);
+                loadedContent = null;
+                setDisplayObject(null);
+                imageWidth = imageHeight = NaN;
+            }
+            else if (drawnDisplayObject)
+            {
+                Sprite(drawnDisplayObject).graphics.clear();
+                clearBitmapData();
+            }
+        }
+
+        /**
+         *  @private
+         */
+        private function clearLoadingContent():void
+        {
+            if (loadingContent is LoaderInfo && LoaderInfo(loadingContent).loader)
+            {
+                try
+                {
+                    LoaderInfo(loadingContent).loader.close();
+                }
+                catch (e:Error)
+                {
+                    // Ignore
+                }
+            }
+
+            removeLoadingListeners();
+            loadingContent = null;
+        }
+
+        /**
+         *  @private
+         */
+        private function clearBitmapData():void
+        {
+            if (_bitmapData)
+            {
+                // Dispose the bitmap if we created it
+                if (bitmapDataCreated)
+                    _bitmapData.dispose();
+                _bitmapData = null;
+            }
+        }
+
+        /**
+         *  @private
+         */
+        private function attachLoadingListeners():void
+        {
+            if (loadingContent)
+            {
+                loadingContent.addEventListener(Event.COMPLETE,
+                    loader_completeHandler, false, 0, true);
+                loadingContent.addEventListener(IOErrorEvent.IO_ERROR,
+                    loader_ioErrorHandler, false, 0, true);
+                loadingContent.addEventListener(ProgressEvent.PROGRESS,
+                    loader_progressHandler, false, 0, true);
+                loadingContent.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
+                    loader_securityErrorHandler, false, 0, true);
+                loadingContent.addEventListener(HTTPStatusEvent.HTTP_STATUS,
+                    dispatchEvent, false, 0, true);
+            }
+        }
+
+        /**
+         *  @private
+         */
+        private function removeLoadingListeners():void
+        {
+            if (loadingContent)
+            {
+                loadingContent.removeEventListener(Event.COMPLETE,
+                    loader_completeHandler);
+                loadingContent.removeEventListener(IOErrorEvent.IO_ERROR,
+                    loader_ioErrorHandler);
+                loadingContent.removeEventListener(ProgressEvent.PROGRESS,
+                    loader_progressHandler);
+                loadingContent.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,
+                    loader_securityErrorHandler);
+                loadingContent.removeEventListener(HTTPStatusEvent.HTTP_STATUS,
+                    dispatchEvent);
+            }
+        }
+
+
+        /**
+         *  @private
+         *  Utility method which is invoked to initiate loading of our
+         *  source.
+         */
+        mx_internal function validateSource():void
+        {
+            if (sourceInvalid || contentLoaderInvalid)
+            {
+                applySource();
+                sourceInvalid = false;
+                contentLoaderInvalid = false;
+            }
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  Event handlers
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  @private
+         */
+        mx_internal function loader_completeHandler(event:Event):void
+        {
+            try
+            {
+                var loaderInfo:LoaderInfo = (event.target is ContentRequest) ?
+                    event.target.content as LoaderInfo : event.target as LoaderInfo;
+
+                if (loaderInfo.bytesLoaded)
+                {
+                    _bytesLoaded = _bytesTotal;
+                    contentComplete(loaderInfo);
+                }
+            }
+            catch (error:SecurityError)
+            {
+                handleSecurityError(error);
+            }
+
+            dispatchEvent(event);
+
+            // Remove any event listeners from load-event dispatcher.
+            clearLoadingContent();
+        }
+
+        /**
+         *  @private
+         */
+        private function loader_ioErrorHandler(error:IOErrorEvent):void
+        {
+            // forward the event, only in the case of a listener, else
+            // an RTE will occur.
+            if (hasEventListener(error.type))
+                dispatchEvent(error);
+
+            // clear any current image and remove any event listeners from
+            // load-event  dispatcher.
+            setBitmapData(null);
+            loadFailed = true;
+        }
+
+        /**
+         *  @private
+         */
+        private function loader_securityErrorHandler(error:SecurityErrorEvent):void
         {
-            finalData = new BitmapData(bitmapData.width * finalScale,
-                bitmapData.height * finalScale, true, 0);
-
-            finalData.draw(bitmapData, new Matrix(finalScale, 0, 0,
-                finalScale), null, null, null, true);
-
-            return finalData;
-        }
-
-        var drop:Number = .5;
-        var initialScale:Number = finalScale;
-
-        while (initialScale/drop < 1)
-            initialScale /= drop;
-
-        var w:Number = Math.floor(bitmapData.width * initialScale);
-        var h:Number = Math.floor(bitmapData.height * initialScale);
-        var bd:BitmapData = new BitmapData(w, h, bitmapData.transparent, 0);
-
-        bd.draw(finalData, new Matrix(initialScale, 0, 0, initialScale),
-            null, null, null, true);
-        finalData = bd;
-
-        for (var scale:Number = initialScale * drop;
-            Math.round(scale * 1000) >= Math.round(finalScale * 1000);
-            scale *= drop)
-        {
-            w = Math.floor(bitmapData.width * scale);
-            h = Math.floor(bitmapData.height * scale);
-            bd = new BitmapData(w, h, bitmapData.transparent, 0);
-
-            bd.draw(finalData, new Matrix(drop, 0, 0, drop), null, null, null, true);
-            finalData.dispose();
-            finalData = bd;
-        }
-
-        return finalData;
-    }
-
-    /**
-     * @private
-     * Invoked upon completion of a load request.
-     */
-    protected function contentComplete(content:Object):void
-    {
-        if (content is LoaderInfo)
-        {
-            // Clear any previous bitmap data or loader instance.
+            dispatchEvent(error);
+
+            // clear any current image and remove any event listeners from
+            // load-event  dispatcher.
             setBitmapData(null);
-            removePreviousContent();
-
-            var loaderInfo:LoaderInfo = content as LoaderInfo;
-
-            if (loaderInfo.childAllowsParent)
-            {
-                // For trusted content we adopt the loaded BitmapData.
-                var image:Bitmap = Bitmap(loaderInfo.content);
-                setBitmapData(image.bitmapData);
-            }
-            else
-            {
-                // For untrusted content we must host the acquired Loader
-                // instance directly as our DisplayObject.
-                displayObjectSharingMode = DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT;
-                invalidateDisplayObjectSharing();
-
-                // Create a content holder to use as our display object.
-                var contentHolder:Sprite = new Sprite();
-                setDisplayObject(contentHolder);
-                loadedContent = loaderInfo.loader;
-                contentHolder.addChild(loadedContent);
-
-                // Retain our source image width and height.
-                imageWidth = loaderInfo.width;
-                imageHeight = loaderInfo.height ;
-
-                // Update
-                invalidateSize();
-                invalidateDisplayList();
-
-                // Denote that we are hosting an untrusted image and as such some
-                // features requiring access to the bitmap data will no longer
-                // function.
-                _trustedSource = false;
-
-                // Dispatch ready event
-                dispatchEvent(new FlexEvent(FlexEvent.READY));
-            }
-        }
-        else
-        {
-            if (content is BitmapData)
-                setBitmapData(content as BitmapData);
-        }
-    }
-
-    /**
-     * @private
-     * Returns true if are to consider aspect ratio while scaling.
-     */
-    private function get maintainAspectRatio():Boolean
-    {
-        return (_scaleMode == BitmapScaleMode.LETTERBOX && _fillMode == BitmapFillMode.SCALE);
-    }
-
-    /**
-     * @private
-     * Removes any previously loaded content prior to loading new.
-     */
-    private function removePreviousContent():void
-    {
-        if (loadedContent && loadedContent.parent)
-        {
-            displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
-            invalidateDisplayObjectSharing();
-            loadedContent.parent.removeChild(loadedContent);
-            loadedContent = null;
-            setDisplayObject(null);
-            imageWidth = imageHeight = NaN;
-        }
-        else if (drawnDisplayObject)
-        {
-            Sprite(drawnDisplayObject).graphics.clear();
-            clearBitmapData();
-        }
-    }
-
-    /**
-     *  @private
-     */
-    private function clearLoadingContent():void
-    {
-        if (loadingContent is LoaderInfo && LoaderInfo(loadingContent).loader)
-        {
-            try
-            {
-                LoaderInfo(loadingContent).loader.close();
-            }
-            catch (e:Error)
-            {
-                // Ignore
-            }
-        }
-
-        removeLoadingListeners();
-        loadingContent = null;
-    }
-
-    /**
-     *  @private
-     */
-    private function clearBitmapData():void
-    {
-        if (_bitmapData)
-        {
-            // Dispose the bitmap if we created it
-            if (bitmapDataCreated)
-                _bitmapData.dispose();
-            _bitmapData = null;
-        }
-    }
-
-    /**
-     *  @private
-     */
-    private function attachLoadingListeners():void
-    {
-        if (loadingContent)
-        {
-            loadingContent.addEventListener(Event.COMPLETE,
-                loader_completeHandler, false, 0, true);
-            loadingContent.addEventListener(IOErrorEvent.IO_ERROR,
-                loader_ioErrorHandler, false, 0, true);
-            loadingContent.addEventListener(ProgressEvent.PROGRESS,
-                loader_progressHandler, false, 0, true);
-            loadingContent.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
-                loader_securityErrorHandler, false, 0, true);
-            loadingContent.addEventListener(HTTPStatusEvent.HTTP_STATUS,
-                dispatchEvent, false, 0, true);
-        }
-    }
-
-    /**
-     *  @private
-     */
-    private function removeLoadingListeners():void
-    {
-        if (loadingContent)
-        {
-            loadingContent.removeEventListener(Event.COMPLETE,
-                loader_completeHandler);
-            loadingContent.removeEventListener(IOErrorEvent.IO_ERROR,
-                loader_ioErrorHandler);
-            loadingContent.removeEventListener(ProgressEvent.PROGRESS,
-                loader_progressHandler);
-            loadingContent.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,
-                loader_securityErrorHandler);
-            loadingContent.removeEventListener(HTTPStatusEvent.HTTP_STATUS,
-                dispatchEvent);
-        }
-    }
-
-
-    /**
-     *  @private
-     *  Utility method which is invoked to initiate loading of our
-     *  source.
-     */
-    mx_internal function validateSource():void
-    {
-        if (sourceInvalid || contentLoaderInvalid)
-        {
+            loadFailed = true;
+        }
+
+        /**
+         *  @private
+         */
+        private function loader_progressHandler(progressEvent:ProgressEvent):void
+        {
+            _bytesLoaded = progressEvent.bytesLoaded;
+            _bytesTotal = progressEvent.bytesTotal;
+
+            // forward the event
+            dispatchEvent(progressEvent);
+        }
+
+        /**
+         *  @private
+         */
+        private function handleSecurityError(error:SecurityError):void
+        {
+            dispatchEvent(new SecurityErrorEvent(SecurityErrorEvent.SECURITY_ERROR,
+                false, false, error.message));
+
+            // clear any current image and remove any event listeners from
+            // load-event  dispatcher.
+            setBitmapData(null);
+            loadFailed = true;
+        }
+
+        /**
+         *  @private
+         *  Used for deferral of bitmap capture when an assigned source
+         *  has yet to be added to the stage.
+         */
+        private function source_addedToStageHandler(event:Event):void
+        {
+            removeAddedToStageHandler(event.target);
             applySource();
-            sourceInvalid = false;
-            contentLoaderInvalid = false;
-        }
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    //  Event handlers
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     *  @private
-     */
-    mx_internal function loader_completeHandler(event:Event):void
-    {
-        try
-        {
-            var loaderInfo:LoaderInfo = (event.target is ContentRequest) ?
-                event.target.content as LoaderInfo : event.target as LoaderInfo;
-
-            if (loaderInfo.bytesLoaded)
-            {
-                _bytesLoaded = _bytesTotal;
-                contentComplete(loaderInfo);
-            }
-        }
-        catch (error:SecurityError)
-        {
-            handleSecurityError(error);
-        }
-
-        dispatchEvent(event);
-
-        // Remove any event listeners from load-event dispatcher.
-        clearLoadingContent();
-    }
-
-    /**
-     *  @private
-     */
-    private function loader_ioErrorHandler(error:IOErrorEvent):void
-    {
-        // forward the event, only in the case of a listener, else
-        // an RTE will occur.
-        if (hasEventListener(error.type))
-            dispatchEvent(error);
-
-        // clear any current image and remove any event listeners from
-        // load-event  dispatcher.
-        setBitmapData(null);
-        loadFailed = true;
-    }
-
-    /**
-     *  @private
-     */
-    private function loader_securityErrorHandler(error:SecurityErrorEvent):void
-    {
-        dispatchEvent(error);
-
-        // clear any current image and remove any event listeners from
-        // load-event  dispatcher.
-        setBitmapData(null);
-        loadFailed = true;
-    }
-
-    /**
-     *  @private
-     */
-    private function loader_progressHandler(progressEvent:ProgressEvent):void
-    {
-        _bytesLoaded = progressEvent.bytesLoaded;
-        _bytesTotal = progressEvent.bytesTotal;
-
-        // forward the event
-        dispatchEvent(progressEvent);
-    }
-
-    /**
-     *  @private
-     */
-    private function handleSecurityError(error:SecurityError):void
-    {
-        dispatchEvent(new SecurityErrorEvent(SecurityErrorEvent.SECURITY_ERROR,
-            false, false, error.message));
-
-        // clear any current image and remove any event listeners from
-        // load-event  dispatcher.
-        setBitmapData(null);
-        loadFailed = true;
-    }
-}
+        }
+
+        /**
+         *  @private
+         */
+        private function removeAddedToStageHandler(target:Object):void
+        {
+            if (target && target is DisplayObject)
+                target.removeEventListener(Event.ADDED_TO_STAGE, source_addedToStageHandler);
+        }
+    }
 }