////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package flashx.textLayout.elements 
{
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.ErrorEvent;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.geom.Rectangle;
    import flash.net.URLRequest;
    import flash.system.Capabilities;
    import flash.text.engine.ContentElement;
    import flash.text.engine.ElementFormat;
    import flash.text.engine.FontMetrics;
    import flash.text.engine.GraphicElement;
    import flash.text.engine.TextBaseline;
    import flash.text.engine.TextLine;
    import flash.text.engine.TextRotation;
    
    import flashx.textLayout.compose.IFlowComposer;
    import flashx.textLayout.compose.ISWFContext;
    import flashx.textLayout.compose.TextFlowLine;
    import flashx.textLayout.debug.Debugging;
    import flashx.textLayout.debug.assert;
    import flashx.textLayout.events.ModelChange;
    import flashx.textLayout.events.StatusChangeEvent;
    import flashx.textLayout.formats.BlockProgression;
    import flashx.textLayout.formats.Float;
    import flashx.textLayout.formats.FormatValue;
    import flashx.textLayout.formats.ITextLayoutFormat;
    import flashx.textLayout.formats.JustificationRule;
    import flashx.textLayout.formats.TextLayoutFormat;
    import flashx.textLayout.property.Property;
    import flashx.textLayout.tlf_internal;
    
    use namespace tlf_internal;

    /** The InlineGraphicElement class handles graphic objects that display inline in the text. 
     * 
     * <p>You can embed a graphic or any DisplayObject or specify a URl for the location of the graphic. 
     * The <code>height</code> and <code>width</code> properties of InlineGraphicElement control the actual size 
     * of the graphic to display.  These values also control how much space to allocate
     * for the graphic in the TextLine object that contains the graphic.
     * The <code>height</code> and <code>width</code> properties each can be one of:</p>
     * <ol>
     * <li>A number of pixels</li>
     * <li>A percent of the measured size of the image</li>
     * <li>The constant, "auto", which computes the size (Default value)</li>
     * </ol>
     * There are three properties, or accessors, pertaining to the width and height of a graphic:
     * <ul>
     * <li>The <code>width</code> and <code>height</code> properties</li>
     * <li>The <code>measuredWidth</code> and <code>measuredHeight</code> properties, which are the width or height of the graphic at load time</li>
     * <li>The <code>actualWidth</code> and <code>actualHeight</code> properties, which are the actual display and compose width and height of the graphic as computed from <code>width</code> or <code>height</code> and <code>measuredWidth</code> or <code>measuredHeight</code></li>
     * </ul>
     * <p>The values of the <code>actualWidth</code> and <code>actualHeight</code> properties are always zero until the graphic 
     * is loaded.</p>
     *
     * <p>If <code>source</code> is specified as a URI, the graphic is loaded asynchronously. If it's a DisplayObject, TextLayout uses the <code>width</code> and 
     * <code>height</code> at the time the graphic is set into the InlineGraphicElement object as <code>measuredHeight</code> and <code>measuredWidth</code>; 
     * its width and height are read immediately.</p>
     * <p><strong>Notes</strong>: For graphics that are loaded asynchronously the user must listen for a 
     * StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE event on the TextFlow and call <code>IFlowComposer.updateAllControllers()</code> to have the 
     * graphic appear. The value of <code>measuredWidth</code> and <code>measuredHeight</code> for graphics that are in the 
     * process of loading is zero.</p>
     *
     * <p>Some inline graphics are animations or videos that possibly have audio. They begin to run the first time they are composed after they finish loading.  
     * They don't stop running until the flowComposer on the TextFlow is set to null.  At that time they are stopped and unloaded.</p>
     * 
     * The following restrictions apply to InLineGraphicElement objects:
     * <ol>
     *  <li>On export of TLFMarkup, source is converted to a string. If the graphic element is 
     *      a class, the Text Layout Framework can't export it properly</li>.
     *  <li>When doing a copy/paste operation of an InlineGraphicElement, if source can't be 
     *      used to create a new InLineGraphicElement, it won't be pasted.  For example if 
     *      source is a DisplayObject, or if the graphic is set directly, it can't be 
     *      duplicated.  Best results are obtained if the source is the class of an embedded graphic 
     *      though that doesn't export/import.</li>
     *  <li>InLineGraphicElement objects work in the factory (TextFlowTextLineFactory) only if 
     *      the source is a class or if you explicitly set the graphic to a loaded graphic. 
     *      InlineGraphic objects that require delayed loads generally do not show up.</li>
     * </ol>
     * @includeExample examples\InlineGraphicElementExample.as -noswf
     *
     * @playerversion Flash 10
     * @playerversion AIR 1.5
     * @langversion 3.0
     *
     * @see #actualHeight
     * @see #actualWidth
     * @see flash.display.DisplayObject DisplayObject
     * @see flashx.textLayout.compose.IFlowComposer#updateAllControllers()
     * @see flashx.textLayout.events.StatusChangeEvent StatusChangeEvent
     * @see TextFlow
     */
    public final class InlineGraphicElement extends FlowLeafElement
    {   
        private var _source:Object;
        
        private var _graphic:DisplayObject;
        private var _placeholderGraphic:Sprite;     // a fake DisplayObject we put in the TextLine so it generates an atom
        
        private var _elementWidth:Number;
        private var _elementHeight:Number;

        // internal status of the graphic.  there are more status here than publicly shown
        private var _graphicStatus:Object;
        
        // set when its ok - must delay until on the stage for dynamically loaded images
        private var okToUpdateHeightAndWidth:Boolean;
        
        private var _width:*;
        private var _height:*;
        
        // stash away the actual width and height of the graphic
        private var _measuredWidth:Number;
        private var _measuredHeight:Number;
        
        private var _float:*;
        
        static private const graphicElementText:String = String.fromCharCode(ContentElement.GRAPHIC_ELEMENT);

        /** Constructor - create new InlineGraphicElement object
         *
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         */
         
        public function InlineGraphicElement()
        {
            super();
            // The width/height on the FE.fe don't actually take until the InlineGraphicElement is loaded.
            okToUpdateHeightAndWidth = false;
            _measuredWidth = 0;
            _measuredHeight = 0;
            internalSetWidth(undefined);
            internalSetHeight(undefined);
            _graphicStatus = InlineGraphicElementStatus.LOAD_PENDING;
            setTextLength(1);
            _text = graphicElementText;     // echo text property we get from FTE
        }
        
        /** @private */
        override tlf_internal function createContentElement():void
        {
            if (_blockElement)
                return;
                
            computedFormat; // BEFORE creating the element
            var graphicElement:GraphicElement = new GraphicElement();           
            _blockElement = graphicElement;
            CONFIG::debug { Debugging.traceFTECall(_blockElement,null,"new GraphicElement()"); }
            
            updateContentElement();

            super.createContentElement();
        }
        
        private function updateContentElement():void
        {
            var graphicElement:GraphicElement = _blockElement as GraphicElement;            
            // Setting textRotation throws if any of the parent GroupElements have textRotation other than ROTATE_0
            CONFIG::debug { assert(_blockElement.textRotation == TextRotation.ROTATE_0,"invalid text Rotation in ILG"); }
            // CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"textRotation",String(rotationPropertyDefinition.defaultValue)); }

            //we need to keep a place holder in the ge.graphic in order to be able to navigate
            //to the element.  Without it, the FTE model will remove the atom and selection will not be
            //possible. - gak 12.12.08
            if (!_placeholderGraphic)
                _placeholderGraphic = new Sprite();
            graphicElement.graphic = _placeholderGraphic;

            if (effectiveFloat != Float.NONE)
            {
                if (graphicElement.elementHeight != 0)
                    graphicElement.elementHeight = 0 ;
                if (graphicElement.elementWidth != 0)
                    graphicElement.elementWidth = 0;
            }
            else
            {
                var height:Number = elementHeightWithMarginsAndPadding();
                if (graphicElement.elementHeight != height)
                    graphicElement.elementHeight = height;
                var width:Number = elementWidthWithMarginsAndPadding();
                if (graphicElement.elementWidth != width)
                    graphicElement.elementWidth = width;
            }
            CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementHeight",graphicElement.elementHeight); }
            CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementWidth",graphicElement.elementWidth); }
            CONFIG::debug { Debugging.traceFTEAssign(graphicElement,"graphic",graphic); }   // needs float fix
        }
        
        // Recalculate graphicElement width & height after a format change
        /** @private */
        public override function get computedFormat():ITextLayoutFormat
        {
            var updateGraphicElement:Boolean = _computedFormat == null;
            super.computedFormat;
            if (updateGraphicElement && _blockElement)
                updateContentElement();

            return _computedFormat;
        }
        
        /** @private */
        tlf_internal function elementWidthWithMarginsAndPadding():Number
        {
            // no textflow is no padding
            var textFlow:TextFlow = getTextFlow();
            if (!textFlow)
                return elementWidth;
            var paddingAmount:Number = textFlow.computedFormat.blockProgression == BlockProgression.RL ? 
                getEffectivePaddingTop()  + getEffectivePaddingBottom() :
                getEffectivePaddingLeft() + getEffectivePaddingRight();
            return elementWidth + paddingAmount;
        }
        
        /** @private */
        tlf_internal function elementHeightWithMarginsAndPadding():Number
        {
            // no textflow is no padding
            var textFlow:TextFlow = getTextFlow();
            if (!textFlow)
				return elementHeight;
            var paddingAmount:Number = textFlow.computedFormat.blockProgression == BlockProgression.RL ? 
                getEffectivePaddingLeft() + getEffectivePaddingRight() :
                getEffectivePaddingTop() + getEffectivePaddingBottom();
            return elementHeight + paddingAmount;
        }
        
        // internal values for _graphicStatus.  It can also be an error code.
        /** load initiated */
        static private const LOAD_INITIATED:String = "loadInitiated";
        /** public status string for open event received status.  @see flash.display.LoaderInfo.Events.open */
        static private const OPEN_RECEIVED:String = "openReceived";
        /** load complete received status.  @see flash.display.LoaderInfo.Events.open */
        static private const LOAD_COMPLETE:String = "loadComplete";
        /** loaded from embed */
        static private const EMBED_LOADED:String = "embedLoaded";
        /** specified as a DisplayObject */
        static private const DISPLAY_OBJECT:String = "displayObject";
        /** null graphic */
        static private const NULL_GRAPHIC:String = "nullGraphic";
        
        
        private static var isMac:Boolean = (Capabilities.os.search("Mac OS") > -1);             
        
        /** The embedded graphic. 
        *
        * @playerversion Flash 10
        * @playerversion AIR 1.5
        * @langversion 3.0
        */
        
        public function get graphic():DisplayObject
        {
            return _graphic;
        }
        private function setGraphic(value:DisplayObject):void
        {
            _graphic = value;
        // I think this should do a model change. But it will break paste because when we paste we do a reimport,
        // which will cause a delayed update, which will bump the generation number *after* the command. Which 
        // will cause undo of the command not to work.
        //  modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
        }
        
        
        /** @private */
        tlf_internal function get placeholderGraphic():Sprite
        {
            return _placeholderGraphic;
        }
        
        /** Width used by composition for laying out text around the graphic. @private */
        tlf_internal function get elementWidth():Number
        {
            return _elementWidth;           
        }
        /** Width used by composition for laying out text around the graphic. @private */
        tlf_internal function set elementWidth(value:Number):void
        {
            _elementWidth = value;

            if (_blockElement)
            {
                (_blockElement as GraphicElement).elementWidth = (effectiveFloat != Float.NONE) ? 0 : elementWidthWithMarginsAndPadding();
                CONFIG::debug { Debugging.traceFTEAssign(GraphicElement(_blockElement as GraphicElement),"elementWidth",GraphicElement(_blockElement).elementWidth); }
                
            }

            modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength,true,false);
        }
        
        /** Height used by composition for laying out text around the graphic. @private */
        tlf_internal function get elementHeight():Number
        {
            return _elementHeight;          
        }
        /** Height used by composition for laying out text around the graphic. @private */
        tlf_internal function set elementHeight(value:Number):void
        {
            _elementHeight = value;

            if (_blockElement)
            {
                (_blockElement as GraphicElement).elementHeight = (effectiveFloat != Float.NONE) ? 0 : elementHeightWithMarginsAndPadding();    
                CONFIG::debug { Debugging.traceFTEAssign((_blockElement as GraphicElement),"elementHeight",GraphicElement(_blockElement).elementHeight); }
            }
            modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength,true,false);
        }
        
        /** Definition of the height property @private */
        static tlf_internal const heightPropertyDefinition:Property = Property.NewNumberOrPercentOrEnumProperty("height", FormatValue.AUTO, false, null, 0, 32000, "0%", "1000000%", FormatValue.AUTO );
        
        /** Definition of the width property @private */
        static tlf_internal const widthPropertyDefinition:Property = Property.NewNumberOrPercentOrEnumProperty("width", FormatValue.AUTO, false, null, 0, 32000, "0%", "1000000%", FormatValue.AUTO );
        
        /** Disabled due to player bug.  @private */
        static tlf_internal const rotationPropertyDefinition:Property = Property.NewEnumStringProperty("rotation", TextRotation.ROTATE_0, false, null, 
            TextRotation.ROTATE_0, TextRotation.ROTATE_90, TextRotation.ROTATE_180, TextRotation.ROTATE_270);       
        
        /** Definition of the float property @private */
        static tlf_internal const floatPropertyDefinition:Property = Property.NewEnumStringProperty("float", Float.NONE, false, null, 
             Float.NONE, Float.LEFT, Float.RIGHT, Float.START, Float.END);
            
        /** The current status of the image. On each status change the owning TextFlow sends a StatusChangeEvent.
         *
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         *
         * @return one of LOAD_PENDING, LOADING, SIZE_PENDING, READY, ERROR
         * @see flashx.textLayout.elements.InlineGraphicElementStatus
         * @see flashx.textLayout.events.StatusChangeEvent
         */
         
        public function get status():String
        {
            switch(_graphicStatus)
            {
                case LOAD_INITIATED:
                case OPEN_RECEIVED:
                    return InlineGraphicElementStatus.LOADING;
                case LOAD_COMPLETE:
                case EMBED_LOADED:
                case DISPLAY_OBJECT:
                case NULL_GRAPHIC:
                    return InlineGraphicElementStatus.READY;
                case InlineGraphicElementStatus.LOAD_PENDING:
                case InlineGraphicElementStatus.SIZE_PENDING:
                    return String(_graphicStatus);
            }
            CONFIG::debug { assert(_graphicStatus is ErrorEvent,"unexpected _graphicStatus"); }
            return InlineGraphicElementStatus.ERROR; 
        }
        
        private function changeGraphicStatus(stat:Object):void
        {
            var oldStatus:String = status;
            _graphicStatus = stat;
            var newStatus:String = status;
            if (oldStatus != newStatus || stat is ErrorEvent)
            {
                var tf:TextFlow = getTextFlow();
                if (tf)
                {
                    if (newStatus == InlineGraphicElementStatus.SIZE_PENDING)
                        tf.processAutoSizeImageLoaded(this);
                    tf.dispatchEvent(new StatusChangeEvent(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, false, false, this, newStatus, stat as ErrorEvent));
                }
            }
        }
                
        /** The width of the graphic. The value can be 'auto', a number of pixels or a percent of the measured width of the image.
         * 
         * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO and flashx.textLayout.formats.FormatValue.INHERIT.</p>
         * <p>Legal values as a number are from 0 to 32000.</p>
         * <p>Legal values as a percent are numbers from 0 to 1000000.</p>
         * <p>Default value is undefined indicating not set.</p>
         * <p>If undefined or "inherit" the InlineGraphicElement will use the default value of "auto".</p>
         * 
         * @throws RangeError when set value is not within range for this property
         * 
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         *
         * @see #actualWidth
         * @see #measuredWidth
         */
        public function get width():*
        { return _width; }
        public function set width(w:*):void
        { 
            internalSetWidth(w);
            modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength);
        }
        
        /** The natural width of the graphic. This is the width of the graphic at load time.
        *
        * @playerversion Flash 10
        * @playerversion AIR 1.5
        * @langversion 3.0
        *
        * @see #actualWidth
        * @see #width
        */
        
        public function get measuredWidth():Number
        { return _measuredWidth; }
        
        /** The actual width in effect. This is the display and compose width that's computed from the
        * <code>width</code> and <code>measuredWidth</code> properties.
        *
        * <p>The values of the <code>actualWidth</code>property are computed according to the 
        * following table:</p>
        * <table class="innertable" width="100%">
        * <tr>
        *   <th>width property</th> 
        *   <th>actualWidth</th>
        * </tr>
        * <tr>
        *   <td>auto</td>
        *   <td>measuredWidth</td>
        * </tr>
        * <tr>
        *   <td>w a Percent</td>
        *   <td>w percent of measuredWidth</td>
        * </tr>
        * <tr>
        *   <td>w a Number</td>
        *   <td>w</td>
        * </tr>
        * </table>
        *
        * <p><strong>Notes</strong>: If the inline graphic is a DisplayObject, its width and height are read immediately.
        * If <code>measuredWidth</code> or <code>measuredHeight</code> are zero, then any auto calculations that would cause a divide by zero sets the result to zero.</p>
        *
        * @playerversion Flash 10
        * @playerversion AIR 1.5
        * @langversion 3.0
        *
        * @see #measuredWidth
        * @see #width
        *
        */
        
        public function get actualWidth():Number
        { return elementWidth; }
        
        private function widthIsComputed():Boolean
        { return internalWidth is String; }
        
        private function get internalWidth():Object
        { return _width === undefined ? widthPropertyDefinition.defaultValue : _width; }        

        private function computeWidth():Number
        {
            CONFIG::debug { assert(widthIsComputed(),"bad call to InlineGraphicElement.computeWidth"); }
            if (internalWidth == FormatValue.AUTO)
            {
                if (internalHeight == FormatValue.AUTO)
                    return _measuredWidth;
                if (_measuredHeight == 0 || _measuredWidth == 0)
                    return 0;
                // can't rely on height being calculated yet
                var effHeight:Number = heightIsComputed() ? computeHeight(): Number(internalHeight);
                return effHeight/_measuredHeight * _measuredWidth;
            }
            return widthPropertyDefinition.computeActualPropertyValue(internalWidth,_measuredWidth); 
        }
        
        private function internalSetWidth(w:*):void
        {
            _width = widthPropertyDefinition.setHelper(width,w);
            elementWidth = widthIsComputed() ? 0 : Number(internalWidth);
            if (okToUpdateHeightAndWidth && graphic)
            {
                if (widthIsComputed())
                    elementWidth =  computeWidth();
                graphic.width = elementWidth;
                CONFIG::debug { Debugging.traceFTEAssign(graphic,"width",elementWidth); }
                if (internalHeight == FormatValue.AUTO)
                {
                    elementHeight =  computeHeight();
                    graphic.height = elementHeight;
                    CONFIG::debug { Debugging.traceFTEAssign(graphic,"height",elementHeight); }
                }
            }
        }

        /** The height of the image. May be 'auto', a number of pixels or a percent of the measured height. 
         *
         * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO and flashx.textLayout.formats.FormatValue.INHERIT.</p>
         * <p>Legal values as a number are from 0 to 32000.</p>
         * <p>Legal values as a percent are numbers from 0 to 1000000.</p>
         * <p>Default value is undefined indicating not set.</p>
         * <p>If undefined or "inherit" the InlineGraphicElement will use the default value of "auto".</p>
         * 
         * @throws RangeError when set value is not within range for this property
         * 
          * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         *
         * @see #actualHeight
         * @see #measuredHeight
         */
        public function get height():*
        { return _height; }
        public function set height(h:*):void
        {
            internalSetHeight(h);
            modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength);
        }
        
        private function get internalHeight():Object
        { return _height === undefined ? heightPropertyDefinition.defaultValue : _height; }
        
        /** @private */
        tlf_internal function get computedFloat():*
        {
            if (_float === undefined)
                return floatPropertyDefinition.defaultValue;
            return _float;
        }
        
        private var _effectiveFloat:String;     // how it was last composed
        /** @private */
        tlf_internal function get effectiveFloat():*
        {
            return _effectiveFloat ? _effectiveFloat : computedFloat;
        }
        /** @private */
        tlf_internal function setEffectiveFloat(floatValue:String):void
        {
            if (_effectiveFloat != floatValue)
            {
                _effectiveFloat = floatValue;
                if (_blockElement)
                    updateContentElement();
            }
        }
        
        [Inspectable(enumeration="none,left,right,start,end")]
        /** 
         * Controls the placement of the graphic relative to the text. It can be part of the line, or can be beside the line with the text 
         * wrapped around it. 
         * <p>Legal values are <code>flashx.textLayout.formats.Float.NONE</code>, <code>flashx.textLayout.formats.Float.LEFT</code>, 
         * <code>flashx.textLayout.formats.Float.RIGHT</code>, <code>flashx.textLayout.formats.Float.START</code>, and <code>flashx.textLayout.formats.Float.END</code>.</p>
         * <p>Default value is undefined indicating not set.</p>
         * <p>If undefined will be treated as <code>Float.NONE</code>.</p>
         * 
         * @throws RangeError when set value is not within range for this property
         * 
         * @see flashx.textLayout.formats.Float
         * 
         * @playerversion Flash 10
         * @playerversion AIR 2.0
         * @langversion 3.0
         */
        public function get float():*
        {
            return _float;
        }
        public function set float(value:*):*
        {
            value = floatPropertyDefinition.setHelper(float, value) as String;
            if (_float != value)
            {
                _float = value;
                if (_blockElement)
                    updateContentElement();
                modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength);
            }                   
        }
        
        /** The natural height of the graphic. This is the height of the graphic at load time.
        *
        * @playerversion Flash 10
        * @playerversion AIR 1.5
        * @langversion 3.0
        * 
        * @see #actualHeight
        * @see #height
        */
        
        public function get measuredHeight():Number
        { return _measuredHeight; }
            
        /** The actual height in effect. This is the display and compose height that's computed from the
        * <code>height</code> and <code>measuredHeight</code> properties.
        *
        * <p>The values of the <code>actualHeight</code> property are computed according to the following table:</p>
        * <table class="innertable" width="100%">
        * <tr>
        *   <th>height property</th>
        *   <th>actualHeight</th>
        * </tr>
        * <tr>
        *   <td>auto</td>
        *   <td>measuredheight</td>
        * </tr>
        * <tr>
        *   <td>h a Percent</td>
        *   <td>h percent of measuredheight</td>
        * </tr>
        * <tr>
        *   <td>h a Number</td>
        *   <td>h</td>
        * </tr>
        * </table>
        * <p><strong>Notes</strong>: If the inline graphic is a DisplayObject, its width and height are read immmediately.
        * If <code>measuredWidth</code> or <code>measuredHeight</code> are zero, then any auto calculations that would cause a divide by zero sets the result to zero.</p>
        *
        * @playerversion Flash 10
        * @playerversion AIR 1.5
        * @langversion 3.0
        *
        * @see #height
        * @see #measuredHeight
        */
        
        public function get actualHeight():Number
        { return elementHeight; }
        
        private function heightIsComputed():Boolean
        { return internalHeight is String; }
        
        private function computeHeight():Number
        {
            CONFIG::debug { assert(heightIsComputed(),"bad call to InlineGraphicElement.computeWidth"); }
            if (internalHeight == FormatValue.AUTO)
            {
                if (internalWidth == FormatValue.AUTO)
                    return _measuredHeight;
                if (_measuredHeight == 0 || _measuredWidth == 0)
                    return 0;
                // can't rely on width being calculated yet
                var effWidth:Number = widthIsComputed() ? computeWidth(): Number(internalWidth);
                return effWidth/_measuredWidth * _measuredHeight;
            }
            return heightPropertyDefinition.computeActualPropertyValue(internalHeight,_measuredHeight); 
        }
        
        private function internalSetHeight(h:*):void
        {
            _height = heightPropertyDefinition.setHelper(height,h);
            elementHeight = heightIsComputed() ? 0 : Number(internalHeight);
            if (okToUpdateHeightAndWidth && graphic != null)
            {
                if (heightIsComputed())
                    elementHeight =  computeHeight();
                graphic.height = elementHeight;
                CONFIG::debug { Debugging.traceFTEAssign(graphic,"height",elementHeight); }

                if (internalWidth == FormatValue.AUTO)
                {
                    elementWidth =  computeWidth();
                    graphic.width = elementWidth;
                    CONFIG::debug { Debugging.traceFTEAssign(graphic,"width",elementWidth); }
                }
            }
        }
        
        private function loadCompleteHandler(e:Event):void
        {           
            CONFIG::debug { Debugging.traceFTECall(null,null,"loadCompleteHandler",this); }
            removeDefaultLoadHandlers(graphic as Loader);
            CONFIG::debug { assert(okToUpdateHeightAndWidth == false,"invalid call to loadCompleteHandler"); }
            okToUpdateHeightAndWidth = true;
			
            var g:DisplayObject = graphic;
            _measuredWidth = g.width;
            _measuredHeight = g.height;
            
			//bug #2931005 TLF cannot show Flex SWF after loading it as an ILG
			if(graphic is Loader && Loader(graphic).content != null && Loader(graphic).content.hasOwnProperty("setActualSize") && (!widthIsComputed() || !heightIsComputed()) )
				Object(Loader(graphic).content).setActualSize(elementWidth, elementHeight);
			else
			{
				if (!widthIsComputed())
                	g.width  = elementWidth;
            	if (!heightIsComputed())
                	g.height = elementHeight;
			}
			
            if (e is IOErrorEvent)
                changeGraphicStatus(e);
            else if (widthIsComputed() || heightIsComputed())
            {
                g.visible = false;
                // triggers a delayedElementUpdate
                changeGraphicStatus(InlineGraphicElementStatus.SIZE_PENDING);
            }
            else
                changeGraphicStatus(LOAD_COMPLETE);
        }
                
        private function openHandler(e:Event):void
        {
            changeGraphicStatus(OPEN_RECEIVED);
        }
        
        private function addDefaultLoadHandlers(loader:Loader):void
        {
            var loaderInfo:LoaderInfo = loader.contentLoaderInfo;
            CONFIG::debug { Debugging.traceFTECall(loaderInfo,loader,"contentLoaderInfo"); }
            
            loaderInfo.addEventListener(Event.OPEN, openHandler, false, 0, true);
            CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",Event.OPEN, "openHandler", false, 0, true); }
            loaderInfo.addEventListener(Event.COMPLETE,loadCompleteHandler,false,0,true);   
            CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",Event.COMPLETE, "loadCompleteHandler", false, 0, true); }
            loaderInfo.addEventListener(IOErrorEvent.IO_ERROR,loadCompleteHandler,false,0,true);    
            CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",IOErrorEvent.IO_ERROR, "loadCompleteHandler", false, 0, true); }
        }
        
        private function removeDefaultLoadHandlers(loader:Loader):void
        {
            CONFIG::debug{ assert(loader != null,"bad call to removeDefaultLoadHandlers"); }
            loader.contentLoaderInfo.removeEventListener(Event.OPEN, openHandler);
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
            loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadCompleteHandler);
        }
        
        /** Sets the source for the graphic. 
         * 
         * The value can be either a String that is interpreted as a URI, a Class that's interpreted as the class of an 
         * embeddded DisplayObject, a DisplayObject instance, or a URLRequest. Creates a DisplayObject and,
         * if the InlineGraphicElement object is added into a ParagraphElement in a TextFlow object, causes it to appear
         * inline in the text.
         *
         * @includeExample examples\InlineGraphicElement_sourceExample.as -noswf
         *
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         */
         
        public function get source():Object
        {
            return _source;
        }
        public function set source(value:Object):void
        {
            stop(true);
            _source = value;
            changeGraphicStatus(InlineGraphicElementStatus.LOAD_PENDING);
            modelChanged(ModelChange.ELEMENT_MODIFIED,this,0,textLength);
        }
    
        /** @private This method starts and stops ILGs.  Generally TLF delays starting an ILG until the first compose.  It shuts them down when they
         * are deleted from the TextFlow or the TextFlow has its flowComposer removed.  Some cases are ambigious, for example removeAllControllers doesn't stop ILGs
         * but the client may desire it too.  In cases where ILGs don't get stopped or started there are two tlf_internal functions on TextFlow:
         * unloadGraphics - unloads and stops all ILGs
         * prepareGraphicsForLoad - puts all ILGs that are not loaded in a list so that they are loaded on the next compose.
         * This function is also called when an auto-size or percentage sized graphic is loaded.  In that case the same list as prepareGraphicsForLoad is used.
         * */
        tlf_internal override function applyDelayedElementUpdate(textFlow:TextFlow,okToUnloadGraphics:Boolean,hasController:Boolean):void
        {
            if (textFlow != this.getTextFlow())
                hasController = false;
            
            CONFIG::debug { assert(textFlow != null,"ILG:applyDelayedElementUpdate: null textFlow"); }      
            if (_graphicStatus == InlineGraphicElementStatus.LOAD_PENDING)
            {
                // trace("FEX LOADING", this.toString());
                if (hasController)
                {
                    var source:Object = _source;
                    if (source is String)
                    {
                        var inlineGraphicResolver:Function = textFlow.configuration.inlineGraphicResolverFunction;
                        if (inlineGraphicResolver != null)
                            source = inlineGraphicResolver(this);
                    }
                    
                    var elem:DisplayObject;
					//change the bug#2929161
					var cILGStatus:String = null;
                    if (source is String || source is URLRequest)
                    {
                        okToUpdateHeightAndWidth = false;
                        var loader:Loader = new Loader();
                        CONFIG::debug { Debugging.traceFTECall(loader,null,"new Loader()"); }

                        // set the width/height on COMPLETE or IOError
                        try
                        {
                            addDefaultLoadHandlers(loader);
                            if (source is String)
                            {
                                var myPattern:RegExp = /\\/g;                           
                                var src:String = source as String;
                                src = src.replace(myPattern, "/");
                                //workaround for Watson bug 1896186.  FlashPlayer requres that file
                                //names be encoded on Macintosh, but not on Windows.  Grouped this
                                //bug with FlashPlayer Watson bug 1899687
                                var pictURLReq:URLRequest;
                                if (isMac)
                                {
                                    pictURLReq = new URLRequest(encodeURI(src));
                                    CONFIG::debug { Debugging.traceFTECall(pictURLReq,null,"new URLRequest",encodeURI(src)); }
                                }
                                else
                                {
                                    pictURLReq = new URLRequest(src);   
                                    CONFIG::debug { Debugging.traceFTECall(pictURLReq,null,"new URLRequest",src); }                                 
                                }
                                
                                loader.load(pictURLReq);
                                CONFIG::debug { Debugging.traceFTECall(null,loader,"load",pictURLReq); }                                    
                            }
                            else
                                loader.load(URLRequest(source));
                                    
							setGraphic(loader);     
                            changeGraphicStatus(LOAD_INITIATED);
							cILGStatus = LOAD_INITIATED;
                        }
                        catch(e:Error)
                        {
                            // the load didn't initiate
                            removeDefaultLoadHandlers(loader);
                            elem = new Shape();
                            changeGraphicStatus(NULL_GRAPHIC);
							cILGStatus = NULL_GRAPHIC;
                        }
                    }
                    else if (source is Class)   // value is class --> it is an Embed
                    {
                        var cls:Class = source as Class;
                        elem = DisplayObject(new cls());
						//change the bug#2929161
						cILGStatus = EMBED_LOADED;
                    }
                    else if (source is DisplayObject)
                    {
                        elem = DisplayObject(source);
						//change the bug#2929161
						cILGStatus = DISPLAY_OBJECT;
                    }
                    else
                    {
                        elem = new Shape();
						//change the bug#2929161
						cILGStatus = NULL_GRAPHIC;
                    }
                    
                    // complete setup of width and height
                    if (cILGStatus != LOAD_INITIATED)
                    {
                        okToUpdateHeightAndWidth = true;
                        _measuredWidth = elem ? elem.width : 0;
                        _measuredHeight = elem ? elem.height : 0;

                        if (widthIsComputed())
                        {
                            if (elem)
                            {
                                elem.width = elementWidth = computeWidth();
                                CONFIG::debug { Debugging.traceFTEAssign(elem,"width",elem.width); }
                            }
                            else
                                elementWidth = 0;
                        }
                        else
                        {
                            elem.width = Number(width);
                            CONFIG::debug { Debugging.traceFTEAssign(elem,"width",elem.width); }
                        }
                            
                        if (heightIsComputed())
                        {
                            if (elem)
                            {
                                elem.height = elementHeight = computeHeight();
                                CONFIG::debug { Debugging.traceFTEAssign(elem,"height",elem.height); }
                            }
                            else
                                elementHeight = 0;
                        }
                        else
                        {
                            elem.height = Number(height);
                            CONFIG::debug { Debugging.traceFTEAssign(elem,"height",elem.height); }
                        }
                        
						setGraphic(elem);
						//change the bug#2929161
						if(cILGStatus!=null)
							changeGraphicStatus(cILGStatus);
                    }
                }
            }
            else
            {
                if (_graphicStatus == InlineGraphicElementStatus.SIZE_PENDING)
                {
                    // this is width/height auto case hasn't been set yet - the graphic is hidden!
                    updateAutoSizes();
                    graphic.visible = true;
                    changeGraphicStatus(LOAD_COMPLETE);
                }
                if (!hasController)
                {
                    // shutdown the audio on any movie clips
                    stop(okToUnloadGraphics);
                }
            }
        }
        
        /** @private This API supports the inputmanager */
        tlf_internal override function updateForMustUseComposer(textFlow:TextFlow):Boolean
        { 
            applyDelayedElementUpdate(textFlow,false,true);
            return status != InlineGraphicElementStatus.READY;
        }
        
        /** This function updates the size of the graphic element when the size is expressed as a percentage of the graphic's actual size. */
        private function updateAutoSizes():void
        {
            if (widthIsComputed())
            {
                elementWidth = computeWidth();
                graphic.width = elementWidth;
            }
            if (heightIsComputed())
            {
                elementHeight = computeHeight();
                graphic.height = elementHeight;
            }
        }
        
        
        /** @private Stop this inlinegraphicelement - if its a movieclip will stop noise and playing - if a load is in process it cancels the load */
        tlf_internal function stop(okToUnloadGraphics:Boolean):Boolean
        {
            
            // watch for changing the source while we've got an event listener on the current graphic
            // if so cancel the load and remove the listeners
            if (_graphicStatus == OPEN_RECEIVED || _graphicStatus == LOAD_INITIATED)
            {
                var loader:Loader = graphic as Loader;
                try
                {
                    loader.close(); // cancels in process load
                }
                catch (e:Error)
                { /* ignore */ }
                removeDefaultLoadHandlers(loader);
            }

            // shutdown any running movieclips - this graphic will no longer be referenced
            // for graphics that the client has passed us - just ignore they own the responsibliity
            if (_graphicStatus != DISPLAY_OBJECT)
            {
                if (okToUnloadGraphics)
                {
                    recursiveShutDownGraphic(graphic);
                    setGraphic(null);
                }
                if (widthIsComputed())
                    elementWidth = 0;
                if (heightIsComputed())
                    elementHeight = 0;
                changeGraphicStatus(InlineGraphicElementStatus.LOAD_PENDING);
            }
            return true;
        }
        
        // searches through the graphic and stops any playing grpahics
        private static function recursiveShutDownGraphic(graphic:DisplayObject):void
        {
            if (graphic is Loader)
                Loader(graphic).unloadAndStop();
            else if (graphic)
            {
                var container:DisplayObjectContainer = graphic as DisplayObjectContainer;
                if (container)
                {
                    for (var idx:int = 0; idx < container.numChildren; idx++)
                    {
                        recursiveShutDownGraphic(container.getChildAt(idx));
                    }
                }

                if (graphic is MovieClip)
                    MovieClip(graphic).stop();
            }
        }
        
        /** @private */
        tlf_internal override function getEffectiveFontSize():Number
        {
            if (effectiveFloat != Float.NONE)
                return 0;
            var defaultLeading:Number = super.getEffectiveFontSize();
            return Math.max(defaultLeading, elementHeightWithMarginsAndPadding());
        }
        
        /** Returns the calculated lineHeight from this element's properties.  @private */
        tlf_internal override function getEffectiveLineHeight(blockProgression:String):Number
        {
            if (effectiveFloat != Float.NONE)
                return 0;
            return super.getEffectiveLineHeight(blockProgression);
        }
        
        /** Returns the typographic ascent of the image (i.e. relative to the line's Roman baseline). @private */
        tlf_internal function getTypographicAscent(textLine:TextLine):Number
        {
            if (effectiveFloat != Float.NONE)
                return 0;
                
            var effectiveHeight:Number = elementHeightWithMarginsAndPadding();
            
            var dominantBaselineString:String;
            if(this._computedFormat.dominantBaseline != FormatValue.AUTO)
            {
                dominantBaselineString = this._computedFormat.dominantBaseline;
            }
            else
            {
                dominantBaselineString = this.getParagraph().getEffectiveDominantBaseline();
            }
            
            var elementFormat:ElementFormat = _blockElement ? _blockElement.elementFormat : computeElementFormat();
            var alignmentBaseline:String = (elementFormat.alignmentBaseline == flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE ? dominantBaselineString : elementFormat.alignmentBaseline);
                
            var top:Number=0;

            // Calcluate relative to dominant baseline; remains 0 for ASCENT and IDEOGRAPHIC_TOP
            if (dominantBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER)
                top += effectiveHeight/2;
            else if (dominantBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM || dominantBaselineString == flash.text.engine.TextBaseline.DESCENT || dominantBaselineString == flash.text.engine.TextBaseline.ROMAN)
                top += effectiveHeight;
                
            // re-jig to be relative to the ROMAN baseline rather than whatever baseline is used for alignment
            top += textLine.getBaselinePosition(flash.text.engine.TextBaseline.ROMAN) - textLine.getBaselinePosition(alignmentBaseline);
            
            // finally, account for baseline shift
            top += elementFormat.baselineShift; 
            
            return top;
        }
        
        /** @private 
         * Get the "inline box" for the element as defined by the CSS visual formatting model (http://www.w3.org/TR/CSS2/visuren.html)
         * For an inline graphic, lineHeight is ignored. The box dimensions are governed by the element height with padding. 
         * Alignment relative to the baseline (using baselineShift, dominantBaseline, alignmentBaseline) is taken into account.
         * @return Null if the element is not "inline" (i.e., is a float). Otherwise, a rectangle representing the inline box. 
         * Top and Bottom are relative to the line's Roman baseline. Left and Right are ignored.
         */
        override tlf_internal function getCSSInlineBox(blockProgression:String, textLine:TextLine, para:ParagraphElement=null, swfContext:ISWFContext=null):Rectangle
        {
            if (effectiveFloat != Float.NONE)
                return null;
            
            var inlineBox:Rectangle = new Rectangle();
            inlineBox.top = -(getTypographicAscent(textLine));
            inlineBox.height = elementHeightWithMarginsAndPadding();
            inlineBox.width = elementWidth;
            
            return inlineBox;
        }
        
        /** @private */
        override tlf_internal function updateIMEAdornments(tLine:TextLine, blockProgression:String, imeStatus:String):void
        {
            // Don't underline for floats
            if (effectiveFloat == Float.NONE)
                super.updateIMEAdornments(tLine, blockProgression, imeStatus);
        }
        
        /** @private */
        override tlf_internal function updateAdornments(tLine:TextLine, blockProgression:String):int
        {
            // Don't underline for floats
            if (effectiveFloat == Float.NONE)
                return super.updateAdornments(tLine, blockProgression);
            return 0;
        }
        
        /** @private */
         public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
        {
            if (endPos == -1)
                endPos = textLength;
                
            var retFlow:InlineGraphicElement = super.shallowCopy(startPos, endPos) as InlineGraphicElement;
            retFlow.source = source;
            retFlow.width = width;
            retFlow.height = height;
            retFlow.float = float;
            
            return retFlow;
        }

         /** @private */
         override protected function get abstract():Boolean
         { return false; }
         
         /** @private */
         tlf_internal override function get defaultTypeName():String
         { return "img"; }      
        
        /** @private */
        tlf_internal override function appendElementsForDelayedUpdate(tf:TextFlow,changeType:String):void
        { 
            if (changeType == ModelChange.ELEMENT_ADDED)
                tf.incGraphicObjectCount();
            else if (changeType == ModelChange.ELEMENT_REMOVAL)
                tf.decGraphicObjectCount();
            
            if (status != InlineGraphicElementStatus.READY || changeType == ModelChange.ELEMENT_REMOVAL)
                tf.appendOneElementForUpdate(this);
        }
        
        /** @private */
        tlf_internal override function calculateStrikeThrough(tLine:TextLine, blockProgression:String, metrics:FontMetrics):Number
        {
            if (!this.graphic || status != InlineGraphicElementStatus.READY)
                return super.calculateStrikeThrough(tLine,blockProgression,metrics);
                
            var stOffset:Number = 0;
            var inlineHolder:DisplayObjectContainer = _placeholderGraphic.parent;
            if (inlineHolder)
            {
                if(blockProgression != BlockProgression.RL)
                    stOffset = placeholderGraphic.parent.y + (this.elementHeight/2 + Number(getEffectivePaddingTop()));
                else
                {
                    var paddingRight:Number = getEffectivePaddingRight();
                    var line:TextFlowLine = tLine.userData as TextFlowLine;
                    var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
                    if(tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
                        stOffset = _placeholderGraphic.parent.x - (this.elementHeight/2 + paddingRight);
                    else
                        stOffset = _placeholderGraphic.parent.x - (this.elementWidth/2 + paddingRight);
                }
            }
            
            return blockProgression == BlockProgression.TB ? stOffset : -stOffset;
        }
    
        /** @private */
        tlf_internal override function calculateUnderlineOffset(stOffset:Number, blockProgression:String, metrics:FontMetrics, tLine:TextLine):Number
        {
            if (!this.graphic || status != InlineGraphicElementStatus.READY)
                return super.calculateUnderlineOffset(stOffset,blockProgression,metrics,tLine);
                
            var para:ParagraphElement = this.getParagraph();
            var ulOffset:Number = 0;
            var inlineHolder:DisplayObjectContainer = _placeholderGraphic.parent;
            if (inlineHolder)
            {
                if(blockProgression == BlockProgression.TB)
                    ulOffset = inlineHolder.y + elementHeightWithMarginsAndPadding();
                else
                {                   
                    if (para.computedFormat.locale.toLowerCase().indexOf("zh") == 0)
                    {
                        ulOffset = inlineHolder.x - elementHeightWithMarginsAndPadding();
                        ulOffset -= metrics.underlineOffset + (metrics.underlineThickness/2);
                        return ulOffset;
                    }
                    else
                        ulOffset = inlineHolder.x - getEffectivePaddingLeft();
                }
            }   
            ulOffset += metrics.underlineOffset + (metrics.underlineThickness/2);
            
            var justRule:String = para.getEffectiveJustificationRule();
            if(justRule == JustificationRule.EAST_ASIAN)
                ulOffset += 1;
        
            return ulOffset;
        }
        // **************************************** 
        // Begin debug support code
        // **************************************** 
        
        /** @private */
        CONFIG::debug public override function toString():String
        {
            return super.toString() + " " + source;
        }
        
        /** @private */
        CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
        {
            // debugging function that asserts if the flow element tree is in an invalid state
            
            var rslt:int = super.debugCheckFlowElement(depth,extraData+" url:"+source);

            if (_blockElement)
                rslt += assert(textLength == (_blockElement as GraphicElement).rawText.length,"image is different than its textElement");
            rslt += assert(this != getParagraph().getLastLeaf(),"last Leaf in paragraph cannot be image");

            return rslt;
        }
    }
}
