////////////////////////////////////////////////////////////////////////////////
//
//  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 elementWidth;
            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;
            
            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;
                    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);
                        }
                        catch(e:Error)
                        {
                            // the load didn't initiate
                            removeDefaultLoadHandlers(loader);
                            elem = new Shape();
                            changeGraphicStatus(NULL_GRAPHIC);
                        }
                    }
                    else if (source is Class)   // value is class --> it is an Embed
                    {
                        var cls:Class = source as Class;
                        elem = DisplayObject(new cls());
                        changeGraphicStatus(EMBED_LOADED);
                    }
                    else if (source is DisplayObject)
                    {
                        elem = DisplayObject(source);
                        changeGraphicStatus(DISPLAY_OBJECT);
                    }
                    else
                    {
                        elem = new Shape();
                        changeGraphicStatus(NULL_GRAPHIC);
                    }
                    
                    // complete setup of width and height
                    if (_graphicStatus != 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);
                    }
                }
            }
            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;
        }
    }
}
