////////////////////////////////////////////////////////////////////////////////
//
//  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.Graphics;
	import flash.display.Shape;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.geom.Rectangle;
	import flash.text.engine.ContentElement;
	import flash.text.engine.ElementFormat;
	import flash.text.engine.FontDescription;
	import flash.text.engine.FontMetrics;
	import flash.text.engine.TextBaseline;
	import flash.text.engine.TextElement;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextLineValidity;
	import flash.text.engine.TextRotation;
	import flash.text.engine.TypographicCase;
	import flash.utils.Dictionary;
	
	import flashx.textLayout.compose.FlowComposerBase;
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.compose.ISWFContext;
	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.events.FlowElementEventDispatcher;
	import flashx.textLayout.events.ModelChange;
	import flashx.textLayout.formats.BackgroundColor;
	import flashx.textLayout.formats.BaselineShift;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.ColorName;
	import flashx.textLayout.formats.FormatValue;
	import flashx.textLayout.formats.IMEStatus;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TLFTypographicCase;
	import flashx.textLayout.formats.TextDecoration;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.CharacterUtil;
	import flashx.textLayout.utils.LocaleUtil;
	
	use namespace tlf_internal;
		
	
	/** Base class for FlowElements that appear at the lowest level of the flow hierarchy. FlowLeafElement objects have
	* no children and include InlineGraphicElement objects and SpanElement objects.
	*
	* @playerversion Flash 10
	* @playerversion AIR 1.5
	* @langversion 3.0
	*
	* @see InlineGraphicElement
	* @see SpanElement
	*/
	public class FlowLeafElement extends FlowElement
	{				
		/** Holds the content of the leaf @private */
		protected var _blockElement:ContentElement;
		
		/** @private
		 * Holds the text for the leaf element - unless there's a valid blockElement, 
		 * in which case the text is in the rawText field of the blockElement.
		 */
		protected var _text:String;	// holds the text property if the blockElement is null
		private var _hasAttachedListeners:Boolean;	// true if FTE eventMirror may be in use
		
		/** @private The event dispatcher that acts as an event mirror */
		tlf_internal var _eventMirror:FlowElementEventDispatcher = null;
		
		/** 
		 * Base class - invoking new FlowLeafElement() throws an error exception. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 */
		public function FlowLeafElement()
		{
			_hasAttachedListeners = false;
			super();
		}
		
		/** @private */
		override tlf_internal function createContentElement():void
		{
			CONFIG::debug { assert(_blockElement != null, "_blockElement not allocated in derived class"); }
			if (_computedFormat)
			{
				_blockElement.elementFormat = computeElementFormat();
				CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementFormat",_blockElement.elementFormat); }
			}
			if (parent)
				parent.insertBlockElement(this,_blockElement);
		}
		/** @private */
		override tlf_internal function releaseContentElement():void
		{
			_blockElement = null;
			_computedFormat = null;
		}
		
		private function blockElementExists():Boolean
		{
			return _blockElement != null;
		}

		/** @private */
		tlf_internal function getBlockElement():ContentElement
		{ 
			if (!_blockElement)
				createContentElement();
			return _blockElement; 
		}
		
		/** @private
		 * Gets the EventDispatcher associated with this FlowElement.  Use the functions
		 * of EventDispatcher such as <code>setEventHandler()</code> and <code>removeEventHandler()</code> 
		 * to capture events that happen over this FlowLeafElement object.  The
		 * event handler that you specify will be called after this FlowElement object does
		 * the processing it needs to do.
		 * 
		 * Note that the event dispatcher will only dispatch FlowElementMouseEvent events.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flash.events.EventDispatcher
		 * @see flashx.textLayout.events.FlowElementMouseEvent
		 */
		tlf_internal override function getEventMirror():IEventDispatcher
		{
			if (!_eventMirror)
				_eventMirror = new FlowElementEventDispatcher(this);
			return _eventMirror;
		}
		
		/** @private
		 * Checks whether an event dispatcher is attached, and if so, if the event dispatcher
		 * has any active listeners.
		 */
		tlf_internal override function hasActiveEventMirror():Boolean
		{
			return _eventMirror && (_eventMirror._listenerCount != 0);
		}
		
		/** @private This is done so that the TextContainerManager can discover EventMirrors in a TextFlow. */
		tlf_internal override function appendElementsForDelayedUpdate(tf:TextFlow,changeType:String):void
		{ 
			if (changeType == ModelChange.ELEMENT_ADDED)
			{
				if (this.hasActiveEventMirror())
				{
					tf.incInteractiveObjectCount();
					getParagraph().incInteractiveChildrenCount() ;
				}
			}
			else if (changeType == ModelChange.ELEMENT_REMOVAL)
			{
				if (this.hasActiveEventMirror())
				{
					tf.decInteractiveObjectCount();
					getParagraph().decInteractiveChildrenCount() ;
				}
			}
			super.appendElementsForDelayedUpdate(tf,changeType);
		}
		
		/**
		 * The text associated with the FlowLeafElement:
		 * <p><ul>
		 * <li>The value for SpanElement subclass will be one character less than <code>textLength</code> if this is the last span in a ParagraphELement.</li>
		 * <li>The value for BreakElement subclass is a U+2028</li>
		 * <li>The value for TabElement subclass is a tab</li>
		 * <li>The value for InlineGraphicElement subclass is U+FDEF</li>
		 * </ul></p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flashx.textLayout.elements.SpanElement#replaceText()
		 */
		public function get text():String
		{
			return _text;
		}
		
		/** @private */
		tlf_internal function getElementFormat():ElementFormat
		{ 			
			if (!_blockElement)
				createContentElement();
			return _blockElement.elementFormat; 
 		}
		
		/** @private */
		tlf_internal override function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
		{
			if (newParent == parent)
				return;
		
			var hasBlock:Boolean = _blockElement != null;
			
			if (_blockElement && parent && parent.hasBlockElement())	// remove textElement from the parent content
				parent.removeBlockElement(this,_blockElement);
			if (newParent && !newParent.hasBlockElement() && _blockElement)
				newParent.createContentElement();
					
			super.setParentAndRelativeStart(newParent,newStart);
			
			// Update the FTE ContentElement structure. If the parent has FTE elements, then create FTE elements for the leaf node 
			// if it doesn't already have them, and add them in. If the parent does not have FTE elements, release the leaf's FTE
			// elements also so they match.
			if (parent)
			{
				if (parent.hasBlockElement())
				{
					if (!_blockElement)
						createContentElement();
					else if (hasBlock)	// don't do this if the _blockElement was constructed as side-effect of setParentAndRelativeStart; in that case, it's already attached
						parent.insertBlockElement(this,_blockElement);
				}
				else if (_blockElement)
					releaseContentElement();
			}
		}
	
		/** @private Only used by SpanElement.splitAtPosition */
		tlf_internal function quickInitializeForSplit(sibling:FlowLeafElement,newSpanLength:int,newSpanTextElement:TextElement):void
		{
			setTextLength(newSpanLength);
			_blockElement = newSpanTextElement;
			if (_blockElement)
				_text = _blockElement.text;
			quickCloneTextLayoutFormat(sibling);
			var tf:TextFlow = sibling.getTextFlow();
			if (tf == null || tf.formatResolver == null)
			{
				_computedFormat = sibling._computedFormat;
				if (_blockElement)
					_blockElement.elementFormat = sibling.getElementFormat();
			}
		}
		
		/**
		 * Returns the next FlowLeafElement object.  
		 * 
		 * @param limitElement	Specifies FlowGroupElement on whose last leaf to stop looking. A value of null (default) 
		 * 	means search till no more elements.
		 * @return 	next FlowLeafElement or null if at the end
		 *
		 * @includeExample examples\FlowLeafElement_getNextLeafExample.as -noswf
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 */
		 
		 public function getNextLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
		{
			if (!parent)
				return null;
			return parent.getNextLeafHelper(limitElement,this);
		}
		
		/**
		 * Returns the previous FlowLeafElement object.  
		 * 
		 * @param limitElement	Specifies the FlowGroupElement on whose first leaf to stop looking.   null (default) means search till no more elements.
		 * @return 	previous leafElement or null if at the end
		 *
		 * @includeExample examples\FlowLeafElement_getPreviousLeafExample.as -noswf
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 */
		 
		public function getPreviousLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
		{
			if (!parent)
				return null;
			return parent.getPreviousLeafHelper(limitElement,this);
		}
		
		/** @private */
		public override function getCharAtPosition(relativePosition:int):String
		{
			return _text ?  _text.charAt(relativePosition) : "";
		} 
		
		/** @private */
		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
		{
			// this does the cascade - potential optimization to skip it if the _blockElement isn't attached
			if (_blockElement)
				computedFormat;
		}
		
		/** Returns the FontMetrics object for the span. The properties of the FontMetrics object describe the 
		 * emBox, strikethrough position, strikethrough thickness, underline position, 
		 * and underline thickness for the specified font. 
		 *
 		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 * @see flash.text.engine.FontMetrics
		 * @see flash.text.engine.ElementFormat#getFontMetrics()
		 *
		 * @return font metrics associated with the span
		 */
		public function getComputedFontMetrics():FontMetrics
		{
			if (!_blockElement)
				createContentElement();
			var ef:ElementFormat = _blockElement.elementFormat;
			if (!ef)
				return null;
				
			var tf:TextFlow = getTextFlow()
			if (tf && tf.flowComposer && tf.flowComposer.swfContext)
				return tf.flowComposer.swfContext.callInContext(ef.getFontMetrics,ef,null,true);
			return ef.getFontMetrics();
		}
		
		/** @private */
		tlf_internal static function resolveDomBaseline(computedFormat:ITextLayoutFormat, para:ParagraphElement):String
		{
			CONFIG::debug { assert(computedFormat != null,"bad call to resolveDomBaseline"); }
			
			var domBase:String = computedFormat.dominantBaseline;
			if(domBase == FormatValue.AUTO)
			{
				if(computedFormat.textRotation == TextRotation.ROTATE_270 /*|| 
					this.computedFormat.blockProgression == BlockProgression.RL*/)
					domBase = TextBaseline.IDEOGRAPHIC_CENTER;
				else
				{
					//otherwise, avoid using the locale of the element and use the paragraph's locale
					if(para != null)
						domBase = para.getEffectiveDominantBaseline();
					else
						domBase = LocaleUtil.dominantBaseline(computedFormat.locale);
				}
			}
			
			return domBase;
		}
		
		/** @private */
		tlf_internal function computeElementFormat():ElementFormat
		{
			CONFIG::debug { assert(_computedFormat != null,"bad call to computeElementFormat"); }

			var tf:TextFlow = getTextFlow();
			return computeElementFormatHelper (_computedFormat, getParagraph(), tf && tf.flowComposer ? tf.flowComposer.swfContext : null);
		}
		
		// mjzhang : fix for bug# 2758977 <s:p color="red"/> throws out of range error - can you do color lookup like Flex SDK
		/** @private */
		static private function translateColor(color:String):Number
		{
			var ret:Number = NaN;
			switch ( color.toLowerCase() )
			{
				case ColorName.BLACK:
					ret = 0x000000; break;
				case ColorName.BLUE:
					ret = 0x0000FF; break;
				case ColorName.GREEN:
					ret = 0x008000; break;
				case ColorName.GRAY: 
					ret = 0x808080; break;
				case ColorName.SILVER: 
					ret = 0xC0C0C0; break;
				case ColorName.LIME: 
					ret = 0x00FF00; break;
				case ColorName.OLIVE: 
					ret = 0x808000; break;
				case ColorName.WHITE: 
					ret = 0xFFFFFF; break;
				case ColorName.YELLOW: 
					ret = 0xFFFF00; break;
				case ColorName.MAROON: 
					ret = 0x800000; break;
				case ColorName.NAVY: 
					ret = 0x000080; break;
				case ColorName.RED: 
					ret = 0xFF0000; break;
				case ColorName.PURPLE: 
					ret = 0x800080; break;
				case ColorName.TEAL: 
					ret = 0x008080; break;
				case ColorName.FUCHSIA: 
					ret = 0xFF00FF; break;
				case ColorName.AQUA: 
					ret = 0x00FFFF; break;
				case ColorName.MAGENTA: 
					ret = 0xFF00FF; break;
				case ColorName.CYAN: 
					ret = 0x00FFFF; break;
				default : break;
			}
			
			return ret;
		}
		
		/** @private */
		static tlf_internal function computeElementFormatHelper(computedFormat:ITextLayoutFormat, para:ParagraphElement, swfContext:ISWFContext):ElementFormat
		{
			// compute the cascaded elementFormat
			var format:ElementFormat = new ElementFormat();
			CONFIG::debug { Debugging.traceFTECall(format,null,"new ElementFormat()"); }
			
			format.alignmentBaseline	= computedFormat.alignmentBaseline;
			format.alpha				= Number(computedFormat.textAlpha);
			format.breakOpportunity		= computedFormat.breakOpportunity;
			format.color				= (computedFormat.color is String) ? translateColor(computedFormat.color) : uint(computedFormat.color);
			format.dominantBaseline		= resolveDomBaseline(computedFormat, para);
			
			format.digitCase			= computedFormat.digitCase;
			format.digitWidth			= computedFormat.digitWidth;
			format.ligatureLevel		= computedFormat.ligatureLevel;
			format.fontSize				= Number(computedFormat.fontSize);
			format.kerning				= computedFormat.kerning;
			format.locale				= computedFormat.locale;
			format.trackingLeft			= TextLayoutFormat.trackingLeftProperty.computeActualPropertyValue(computedFormat.trackingLeft,format.fontSize);
			format.trackingRight		= TextLayoutFormat.trackingRightProperty.computeActualPropertyValue(computedFormat.trackingRight,format.fontSize);
			format.textRotation			= computedFormat.textRotation;
			format.baselineShift 		= -(TextLayoutFormat.baselineShiftProperty.computeActualPropertyValue(computedFormat.baselineShift, format.fontSize));
			switch (computedFormat.typographicCase)
			{
				case TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS:
					format.typographicCase = TypographicCase.CAPS_AND_SMALL_CAPS;
					break;
				case TLFTypographicCase.CAPS_TO_SMALL_CAPS:
					format.typographicCase = TypographicCase.SMALL_CAPS;
					break;
				/* Others map directly so handle it in the default case */
				default:
					format.typographicCase = computedFormat.typographicCase;
					break;
			}
			
			CONFIG::debug { Debugging.traceFTEAssign(format,"alignmentBaseline",format.alignmentBaseline); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"alpha",format.alpha); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"breakOpportunity",format.breakOpportunity); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"color",format.color); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"dominantBaseline",format.dominantBaseline); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"digitCase",format.digitCase); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"digitWidth",format.digitWidth); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"ligatureLevel",format.ligatureLevel); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"fontSize",format.fontSize); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"kerning",format.kerning); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"locale",format.locale); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"trackingLeft",format.trackingLeft); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"trackingRight",format.trackingRight); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"typographicCase",format.typographicCase); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"textRotation",format.textRotation); }
			CONFIG::debug { Debugging.traceFTEAssign(format,"baselineShift",format.baselineShift);	 }	
			
			// set the fontDesription in the cascadedFormat
			var fd:FontDescription = new FontDescription();
			fd.fontWeight = computedFormat.fontWeight;
			fd.fontPosture = computedFormat.fontStyle;
			fd.fontName = computedFormat.fontFamily;
			fd.renderingMode = computedFormat.renderingMode;
			fd.cffHinting = computedFormat.cffHinting;
			
			// the fontLookup may be override by the resolveFontLookupFunction
			if (GlobalSettings.resolveFontLookupFunction == null)
				fd.fontLookup = computedFormat.fontLookup;
			else
			{
				fd.fontLookup = GlobalSettings.resolveFontLookupFunction(swfContext ? FlowComposerBase.computeBaseSWFContext(swfContext) : null, computedFormat);
			}
			// and now give the fontMapper a shot at rewriting the FontDescription
			var fontMapper:Function = GlobalSettings.fontMapperFunction;
			if (fontMapper != null)
				fontMapper(fd);
			CONFIG::debug { Debugging.traceFTECall(fd,null,"new FontDescription()"); }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"fontWeight",fd.fontWeight);	 }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"fontPosture",fd.fontPosture);	 }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"fontName",fd.fontName);	 }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"renderingMode",fd.renderingMode);	 }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"cffHinting",fd.cffHinting);	 }
			CONFIG::debug { Debugging.traceFTEAssign(fd,"fontLookup",fd.fontLookup);	 }
			
			format.fontDescription = fd;
			CONFIG::debug { Debugging.traceFTEAssign(format,"fontDescription",fd); }
			
			//Moved code here because original code tried to access fontMetrics prior to setting the elementFormat.
			//Since getFontMetrics returns the value of blockElement.elementFormat.getFontMetrics(), we cannot call this
			//until after the element has been set. Watson 1820571 - gak 06.11.08
			// Adjust format for superscript/subscript
			if (computedFormat.baselineShift == BaselineShift.SUPERSCRIPT || 
				computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
			{
				var fontMetrics:FontMetrics;
				if (swfContext)
					fontMetrics = swfContext.callInContext(format.getFontMetrics,format,null,true);
				else	
					fontMetrics = format.getFontMetrics();	
				if (computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
				{
					format.baselineShift = (fontMetrics.superscriptOffset * format.fontSize);
					format.fontSize = fontMetrics.superscriptScale * format.fontSize;
				}
				else // it's subscript
				{
					format.baselineShift = (fontMetrics.subscriptOffset * format.fontSize);
					format.fontSize = fontMetrics.subscriptScale * format.fontSize;
				}
				CONFIG::debug { Debugging.traceFTEAssign(format,"baselineShift",format.baselineShift); }
				CONFIG::debug { Debugging.traceFTEAssign(format,"fontSize",format.fontSize); }
			}			
			return format;
		}

		/** 
		 * The computed text format attributes that are in effect for this element.
		 * Takes into account the inheritance of attributes.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 * @see flashx.textLayout.formats.ITextLayoutFormat
		 */
		public override function get computedFormat():ITextLayoutFormat
		{		
			if (!_computedFormat)
			{
				_computedFormat = doComputeTextLayoutFormat();

				if (_blockElement)
				{
					_blockElement.elementFormat = computeElementFormat();
					CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementFormat",_blockElement.elementFormat); }
				}

			}
			return _computedFormat;
		}
		
		/** Returns the calculated lineHeight from this element's properties.  @private */
		tlf_internal function getEffectiveLineHeight(blockProgression:String):Number
		{
			//ignore the leading on a TCY Block. If the element is in a TCYBlock, it has no leading
			if (blockProgression == BlockProgression.RL && (parent is TCYElement))
				return 0;
			CONFIG::debug { assert(_computedFormat != null,"Missing _computedFormat in FlowLeafElement.getEffectiveLineHeight"); }
			return TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(_computedFormat.lineHeight, getEffectiveFontSize());
		}
		
		/** @private 
		 * Get the "inline box" for the element as defined by the CSS visual formatting model (http://www.w3.org/TR/CSS2/visuren.html)
		 * @param	blockProgression	Block progression
		 * @param	textLine			The containing text line
		 * @param	para				The containing para. Only used for resolving AUTO dominantBaseline value. 
		 * 								May be null, in which case the AUTO dominantBaseline value is resolved based on other attributes (such as the element's computed locale). 	
		 * @param	swfContext			The SWF context in which certain method calls (such as the one used to get font metrics) are made
		 * 								May be null in which case the current SWF context is used.
		 * @return 						Null if the element is not "inline"
		 * 								Otherwise, a rectangle representing the inline box. Top and Bottom are relative to the line's Roman baseline. Left and Right are ignored.
		 */
		tlf_internal function getCSSInlineBox(blockProgression:String, textLine:TextLine, para:ParagraphElement=null, swfContext:ISWFContext=null):Rectangle
		{
			// TODO-9/27/10: TCYs typically don't affect leading, but this may not be appropriate for LeadingModel.BOX 
			if (blockProgression == BlockProgression.RL && (parent is TCYElement))
				return null;
			
			return getCSSInlineBoxHelper (computedFormat, getComputedFontMetrics(), textLine, para);
		}
		
		/** @private 
		 * Get the "inline box" for an element with the specified computed format as defined by the CSS visual formatting model (http://www.w3.org/TR/CSS2/visuren.html)
		 * For a span, leading is applied equally above and below the em-box such that the box's height equals lineHeight. 
		 * Alignment relative to the baseline (using baselineShift, dominantBaseline, alignmentBaseline) is taken into account.
		 * @param	textLine		The containing text line
		 * @param	para			The containing para. Only used for resolving AUTO dominantBaseline value. 
		 * 							May be null, in which case the AUTO dominantBaseline value is resolved based on other attributes (such as the element's computed locale). 	
		 * @return 	A rectangle representing the inline box. Top and Bottom are relative to the line's Roman baseline. Left and Right are ignored.
		 */
		static tlf_internal function getCSSInlineBoxHelper(computedFormat:ITextLayoutFormat, metrics:FontMetrics, textLine:TextLine, para:ParagraphElement=null):Rectangle
		{
			var emBox:Rectangle 	= metrics.emBox;
			
			var ascent:Number 		= -emBox.top;
			var descent:Number 		= emBox.bottom;
			var textHeight:Number	= emBox.height;
			
			var fontSize:Number 	= computedFormat.fontSize;
			var lineHeight:Number 	= TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(computedFormat.lineHeight, fontSize);
			var halfLeading:Number	= (lineHeight - textHeight) / 2;
			
			// Apply half leading equally above and below the em box
			emBox.top -= halfLeading;
			emBox.bottom += halfLeading;
			
			// Account for the effect of dominantBaseline
			var computedDominantBaseline:String = resolveDomBaseline(computedFormat, para);
			switch (computedDominantBaseline)
			{
				case TextBaseline.ASCENT:
				case TextBaseline.IDEOGRAPHIC_TOP:
					emBox.offset(0, ascent); 
					break;
				
				case TextBaseline.IDEOGRAPHIC_CENTER:
					emBox.offset(0, ascent - textHeight/2);
					break;
				
				case TextBaseline.ROMAN:
					break;
				
				case TextBaseline.DESCENT:
				case TextBaseline.IDEOGRAPHIC_BOTTOM:
					emBox.offset(0, -descent);
			}
			
			// Account for the effect of alignmentBaseline
			var computedAlignmentBaseline:String = (computedFormat.alignmentBaseline == TextBaseline.USE_DOMINANT_BASELINE ? computedDominantBaseline : computedFormat.alignmentBaseline);
			emBox.offset(0, textLine.getBaselinePosition(computedAlignmentBaseline));
			
			// Account for the effect of baselineShift
			var baselineShift:Number;
			if (computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
				baselineShift = metrics.superscriptOffset * fontSize;
			else if (computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
				baselineShift = metrics.subscriptOffset * fontSize;
			else
				baselineShift = -computedFormat.baselineShift;
			
			emBox.offset(0, baselineShift);
			
			return emBox;
		}
		
		/** Returns the fontSize from this element's properties.  @private */
		tlf_internal function getEffectiveFontSize():Number
		{
			return Number(computedFormat.fontSize);
		}
		
		/** @private */
		tlf_internal function getSpanBoundsOnLine(textLine:TextLine, blockProgression:String):Array
		{
			var line:TextFlowLine = TextFlowLine(textLine.userData);
			var paraStart:int = line.paragraph.getAbsoluteStart();
			var lineEnd:int = (line.absoluteStart + line.textLength) - paraStart;
			var spanStart:int = getAbsoluteStart() - paraStart;		// get start pos relative to the paragraph (which might not be the parent)
			var endPos:int = spanStart + text.length;		// so we don't include the paragraph terminator character, if present
		
			// Clip to start of line	
			var startPos:int = Math.max(spanStart, line.absoluteStart - paraStart);
			
			// Clip to end of line	
			// Heuristic for detecting spaces at the end of the line and eliminating them from the range so they won't be underlined.
			if (endPos >= lineEnd)
			{
				endPos = lineEnd;
				var spanText:String = text;
				while (endPos > startPos && CharacterUtil.isWhitespace(spanText.charCodeAt(endPos - spanStart - 1)))
					--endPos;
			}

			var mainRects:Array = [];
			line.calculateSelectionBounds(textLine, mainRects, startPos, endPos, blockProgression, [ line.textHeight,0]);
			return mainRects;
		}
		
		/** @private */
		tlf_internal function updateIMEAdornments(tLine:TextLine, blockProgression:String, imeStatus:String):void
		{
			var metrics:FontMetrics = getComputedFontMetrics();
			var spanBoundsArray:Array = getSpanBoundsOnLine(tLine, blockProgression);
			//this is pretty much always going to have a length of 1, but just to be sure...
			for (var i:int = 0; i < spanBoundsArray.length; i++)
			{
				//setup ime variables
				var imeLineThickness:int = 1;
				var imeLineColor:uint = 0x000000;
				var imeLineStartX:Number = 0;
				var imeLineStartY:Number = 0;
				var imeLineEndX:Number = 0;
				var imeLineEndY:Number = 0;
				
				//selected text draws with 2 px
				if(imeStatus == IMEStatus.SELECTED_CONVERTED || imeStatus == IMEStatus.SELECTED_RAW)
				{
					imeLineThickness = 2;
				}
				//Raw or deadkey text draws with grey
				if(imeStatus == IMEStatus.SELECTED_RAW || imeStatus == IMEStatus.NOT_SELECTED_RAW
					|| imeStatus == IMEStatus.DEAD_KEY_INPUT_STATE)
				{
					imeLineColor = 0xA6A6A6;
				}
				
				var spanBounds:Rectangle = spanBoundsArray[i] as Rectangle;
				var stOffset:Number = calculateStrikeThrough(tLine, blockProgression, metrics);
				var ulOffset:Number = calculateUnderlineOffset(stOffset, blockProgression, metrics, tLine);
				
				if (blockProgression != BlockProgression.RL)
				{
					imeLineStartX = spanBounds.topLeft.x + 1;
					imeLineEndX = spanBounds.topLeft.x + spanBounds.width - 1;
					imeLineStartY = ulOffset;
					imeLineEndY = ulOffset;
				}
				else
				{
					//is this TCY?
					var line:TextFlowLine = tLine.userData as TextFlowLine;
					var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
					imeLineStartY = spanBounds.topLeft.y + 1;
					imeLineEndY = spanBounds.topLeft.y + spanBounds.height - 1;
					
					//elemIdx can sometimes be negative if the text is being wrapped due to a
					//resize gesture - in which case the tLine has not necessarily been updated.
					//If the elemIdx is invalid, just treat it like it's normal ttb text - gak 07.08.08
					if(elemIdx < 0 || tLine.atomCount <= elemIdx || tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
					{
						imeLineStartX = ulOffset;
						imeLineEndX = ulOffset;
					}
					else
					{
						//it is TCY!
						var tcyParent:TCYElement =  this.getParentByType(TCYElement) as TCYElement;
						CONFIG::debug{ assert(tcyParent != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
						
						//only perform calculations for TCY adornments when we are on the last leaf.  ONLY the last leaf matters
						if((this.getAbsoluteStart() + this.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
						{
							var tcyAdornBounds:Rectangle = new Rectangle();	// NO PMD
							tcyParent.calculateAdornmentBounds(tcyParent, tLine, blockProgression, tcyAdornBounds);
							var baseULAdjustment:Number = metrics.underlineOffset + (metrics.underlineThickness/2);
							
							imeLineStartY = tcyAdornBounds.top + 1;
							imeLineEndY = tcyAdornBounds.bottom - 1;
							imeLineStartX = spanBounds.bottomRight.x + baseULAdjustment;
							imeLineEndX = spanBounds.bottomRight.x + baseULAdjustment;
						}
					}
				}
				
				//Build the shape
				var selObj:Shape = new Shape();	// NO PMD
				//TODO - this is probably going to need to be overridable in the full implementation
				selObj.alpha = 1;       				
				selObj.graphics.beginFill(imeLineColor);
				
				selObj.graphics.lineStyle(imeLineThickness, imeLineColor, selObj.alpha);
				selObj.graphics.moveTo(imeLineStartX, imeLineStartY);
				selObj.graphics.lineTo(imeLineEndX, imeLineEndY);
				
				selObj.graphics.endFill();
				tLine.addChild(selObj);
			}
		}
		
		
		/** @private return number of shapes added */
		tlf_internal function updateAdornments(tLine:TextLine, blockProgression:String):int
		{
			CONFIG::debug { assert(_computedFormat != null,"invalid call to updateAdornments"); }

			// Only work on lines with strikethrough or underline
			if (_computedFormat.textDecoration == TextDecoration.UNDERLINE || _computedFormat.lineThrough || _computedFormat.backgroundAlpha > 0 && _computedFormat.backgroundColor != BackgroundColor.TRANSPARENT)
			{
				var spanBoundsArray:Array = getSpanBoundsOnLine(tLine, blockProgression);
				for (var i:int = 0; i < spanBoundsArray.length; i++)
					updateAdornmentsOnBounds(tLine, blockProgression, spanBoundsArray[i]);
				return spanBoundsArray.length ;
			}
			return 0;
		}
		 
		private function updateAdornmentsOnBounds(tLine:TextLine, blockProgression:String, spanBounds:Rectangle):void
		{
			CONFIG::debug { assert(_computedFormat != null,"invalid call to updateAdornmentsOnBounds"); }

			var metrics:FontMetrics = getComputedFontMetrics();


			var backgroundOnly:Boolean = !(_computedFormat.textDecoration == TextDecoration.UNDERLINE || _computedFormat.lineThrough);
				
			if (!backgroundOnly)
			{
				var shape:Shape;
				var g:Graphics;
				shape = new Shape();
				shape.alpha = Number(_computedFormat.textAlpha);
				g = shape.graphics;
						
				var stOffset:Number = calculateStrikeThrough(tLine, blockProgression, metrics);
				var ulOffset:Number = calculateUnderlineOffset(stOffset, blockProgression, metrics, tLine);
			}
						
			if (blockProgression != BlockProgression.RL)
			{
				addBackgroundRect (tLine, metrics, spanBounds, true); 

				if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
				{
					g.lineStyle(metrics.underlineThickness, _computedFormat.color as uint);
					g.moveTo(spanBounds.topLeft.x, ulOffset);
					g.lineTo(spanBounds.topLeft.x + spanBounds.width, ulOffset);
				}
				
				if((_computedFormat.lineThrough))
				{
					g.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint);
					g.moveTo(spanBounds.topLeft.x, stOffset);
					g.lineTo(spanBounds.topLeft.x + spanBounds.width, stOffset);
				}
			}
			else
			{
				//is this TCY?
				var line:TextFlowLine = tLine.userData as TextFlowLine;
				var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
				
				//elemIdx can sometimes be negative if the text is being wrapped due to a
				//resize gesture - in which case the tLine has not necessarily been updated.
				//If the elemIdx is invalid, just treat it like it's normal ttb text - gak 07.08.08
				if (elemIdx < 0 || tLine.atomCount <= elemIdx || tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
				{
					addBackgroundRect (tLine, metrics, spanBounds, false);

					if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
					{
						g.lineStyle(metrics.underlineThickness, _computedFormat.color as uint);
						g.moveTo(ulOffset, spanBounds.topLeft.y);
						g.lineTo(ulOffset, spanBounds.topLeft.y + spanBounds.height);
					}
					
					if (_computedFormat.lineThrough == true)
					{
						g.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint);
						g.moveTo(-stOffset, spanBounds.topLeft.y);
						g.lineTo(-stOffset, spanBounds.topLeft.y + spanBounds.height);															
					}
				}
				else
				{
					addBackgroundRect (tLine, metrics, spanBounds, true, true); 
					
					if (!backgroundOnly)
					{
						//it is TCY!
						var tcyParent:TCYElement =  this.getParentByType(TCYElement) as TCYElement;
						CONFIG::debug{ assert(tcyParent != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
						
						//if the locale of the paragraph is Chinese, we need to adorn along the left and not right side.
						var tcyPara:ParagraphElement = this.getParentByType(ParagraphElement) as ParagraphElement;
						var lowerLocale:String = tcyPara.computedFormat.locale.toLowerCase();
						var adornRight:Boolean = (lowerLocale.indexOf("zh") != 0);
						
						
						//only perform calculations for TCY adornments when we are on the last leaf.  ONLY the last leaf matters
						if((this.getAbsoluteStart() + this.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
						{
							var tcyAdornBounds:Rectangle = new Rectangle();
							tcyParent.calculateAdornmentBounds(tcyParent, tLine, blockProgression, tcyAdornBounds);
							
							if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
							{
								g.lineStyle(metrics.underlineThickness, _computedFormat.color as uint);
								var baseULAdjustment:Number = metrics.underlineOffset + (metrics.underlineThickness/2);
								var xCoor:Number = adornRight ? spanBounds.right : spanBounds.left;
								if(!adornRight)
									baseULAdjustment = -baseULAdjustment;
								
								g.moveTo(xCoor + baseULAdjustment, tcyAdornBounds.top);
								g.lineTo(xCoor + baseULAdjustment, tcyAdornBounds.bottom);
							}
	
							if (_computedFormat.lineThrough == true)
							{
								var tcyMid:Number = spanBounds.bottomRight.x - tcyAdornBounds.x;
								tcyMid /= 2;
								tcyMid += tcyAdornBounds.x;
								
								g.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint);
								g.moveTo(tcyMid, tcyAdornBounds.top);
								g.lineTo(tcyMid, tcyAdornBounds.bottom);
							}
						}
					}
				}
			}
			
		 	// Add the shape as a child of the TextLine. In some cases, the textLine we passed through may not be the same one that's
			// in the TextFlowLine textLineCache. This can happen if the TextFlowLine's textLine is invalid and a child of the 
			// container. In that case, we generated a valid TextLine and passed it in as tLine so that we have correct metrics 
			// for generating the adornment shapes.
			if (shape)
			{
	 			var peekLine:TextLine = (tLine.userData as TextFlowLine).peekTextLine();
				CONFIG::debug{ assert(peekLine == null || peekLine == tLine || peekLine.validity == TextLineValidity.INVALID, "Valid/invalid mismatch"); }
				// CONFIG::debug{ assert(peekLine == null || peekLine == TextFlowLine(tLine.userData).getTextLine(false), "Valid/invalid mismatch"); }
				if (peekLine && tLine != peekLine)
				{
					// belief is that this line of code is never hit
					CONFIG::debug { assert(false,"updateAdornmentsOnBounds: peekLine doesn't match textLine"); }
					tLine = peekLine;
				}
				tLine.addChild(shape);
			}
		}
		
		/** @private
		 * Adds the background rectangle (if needed), making adjustments for glyph shifting as appropriate
		 */
		 private function addBackgroundRect(tLine:TextLine, metrics:FontMetrics, spanBounds:Rectangle, horizontalText:Boolean, isTCY:Boolean=false):void
		 {
			if(_computedFormat.backgroundAlpha == 0 || _computedFormat.backgroundColor == BackgroundColor.TRANSPARENT)
				return;
				
			var tf:TextFlow = this.getTextFlow();
			// ensure the TextFlow has a background manager - but its only supported with the StandardFlowComposer at this time			
			if (!tf.getBackgroundManager())
				return;
					
			// The background rectangle usually needs to coincide with the passsed-in span bounds.
			var r:Rectangle = spanBounds.clone();
			
			// With constrained glyph shifting (such as when superscript/subscript are in use), we'd like the
			// background rectangle to follow the glyphs. Not so for arbitrary glyph shifting (such as when 
			// baseline shift or baseline alignment are in use)	 	
			// TODO-06/12/2009: Need to figure out adjustment for TCY background rect. No adjustment for now.
			if (!isTCY && (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT || _computedFormat.baselineShift == BaselineShift.SUBSCRIPT))
			{	
				// The atom bounds returned by FTE do not reflect the effect of glyph shifting.
				// We approximate this effect by making the following assumptions (strikethrough/underline code does the same)
				// - The strike-through adornment runs through the center of the glyph
				// - The Roman baseline is halfway between the center and bottom (descent)
				// Effectively, the glyph's descent equals the strike-through offset, and its ascent is three times that
				
				var desiredExtent:Number; // The desired extent of the rectangle in the block progression direction
				var baselineShift:Number; 
				var fontSize:Number = getEffectiveFontSize();
				var baseStrikethroughOffset:Number = metrics.strikethroughOffset + metrics.strikethroughThickness/2;
				
				if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
				{
					// The rectangle needs to sit on the line's descent and must extend far enough to accommodate the
					// ascender of the glyph (that has moved up because of superscript)
					
					var glyphAscent:Number = -3 * baseStrikethroughOffset; // see assumptions above
					baselineShift = -metrics.superscriptOffset * fontSize;
					var lineDescent:Number = tLine.getBaselinePosition(TextBaseline.DESCENT) - tLine.getBaselinePosition(TextBaseline.ROMAN);
					
					desiredExtent = glyphAscent  + baselineShift + lineDescent;
					if (horizontalText)
					{
						if (desiredExtent > r.height)
						{
							r.y -= desiredExtent - r.height;
							r.height = desiredExtent;
						}
					}
					else
					{
						if (desiredExtent > r.width)
							r.width = desiredExtent;
					}
				}
				else
				{
					// The rectangle needs to hang from the line's ascent and must extend far enough to accommodate the
					// descender of the glyph (that has moved down because of superscript)
					
					var glyphDescent:Number = -baseStrikethroughOffset; // see assumptions above
					baselineShift = metrics.subscriptOffset * fontSize; 
					var lineAscent:Number = tLine.getBaselinePosition(TextBaseline.ROMAN) - tLine.getBaselinePosition(TextBaseline.ASCENT);
					
					desiredExtent = lineAscent + baselineShift + glyphDescent;
					if (horizontalText)
					{
						if (desiredExtent > r.height)
							r.height = desiredExtent;
					}
					else
					{
						if (desiredExtent > r.width)
						{
							r.x -= desiredExtent - r.width
							r.width = desiredExtent;
						}
					}
				}
			}
			
			tf.backgroundManager.addRect(tLine, this, r, _computedFormat.backgroundColor, _computedFormat.backgroundAlpha);	 
		}

		/** @private */
		tlf_internal function calculateStrikeThrough(textLine:TextLine, blockProgression:String, metrics:FontMetrics):Number
		{
			var underlineAndStrikeThroughShift:int = 0;	
			var effectiveFontSize:Number = this.getEffectiveFontSize()
			if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
			{
				underlineAndStrikeThroughShift = -(metrics.superscriptOffset * effectiveFontSize);
			} else if (_computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
			{
				underlineAndStrikeThroughShift = -(metrics.subscriptOffset * (effectiveFontSize / metrics.subscriptScale));
			} else {
				underlineAndStrikeThroughShift = TextLayoutFormat.baselineShiftProperty.computeActualPropertyValue(_computedFormat.baselineShift, effectiveFontSize);
			}
			
			//grab the dominantBaseline and alignmentBaseline strings
			var domBaselineString:String = resolveDomBaseline(computedFormat, getParagraph());
			var alignmentBaselineString:String = this.computedFormat.alignmentBaseline;
			
			//this value represents the position of the baseline used to align this text
			var alignDomBaselineAdjustment:Number = textLine.getBaselinePosition(domBaselineString);
			
			//if the alignment baseline differs from the dominant, then we need to apply the delta between the
			//dominant and the alignment to determine the line along which the glyphs are lining up...
			if(alignmentBaselineString != flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE && 
				alignmentBaselineString != domBaselineString)
			{
				alignDomBaselineAdjustment = textLine.getBaselinePosition(alignmentBaselineString);
				//take the alignmentBaseline offset and make it relative to the dominantBaseline
			}
			
			
			//first, establish the offset relative to the glyph based in fontMetrics data
			var stOffset:Number = metrics.strikethroughOffset;
			
			
			//why are we using the stOffset?  Well, the stOffset effectively tells us where the mid-point
			//of the glyph is.  By using this value, we can determine how we need to offset the underline.
			//now adjust the value.  If it is center, then the glyphs are aligned along the ST position already
			if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER)
			{
				stOffset = 0;
			}
			else if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP || 
				domBaselineString == flash.text.engine.TextBaseline.ASCENT)
			{
				stOffset *= -2;  //if the glyphs are top or ascent, then we need to invert and double the offset
				stOffset -= (2 * metrics.strikethroughThickness);
			}
			else if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM || 
				domBaselineString == flash.text.engine.TextBaseline.DESCENT)
			{
				stOffset *= 2; //if they're bottom, then we need to simply double it
				stOffset += (2 * metrics.strikethroughThickness);
			}
			else //Roman
			{
				stOffset -= metrics.strikethroughThickness;
			}
			
			
			//Now apply the actual dominant baseline position to the offset
			stOffset += (alignDomBaselineAdjustment - underlineAndStrikeThroughShift);
			return stOffset;
		}
		
		/** @private */
		tlf_internal function calculateUnderlineOffset(stOffset:Number, blockProgression:String, metrics:FontMetrics, textLine:TextLine):Number
		{
			var ulOffset:Number = metrics.underlineOffset + metrics.underlineThickness;
			var baseSTAdjustment:Number = metrics.strikethroughOffset;
			
			//based on the stOffset - which really represents the middle of the glyph, set the ulOffset
			//which will always be relative.  Note that simply using the alignDomBaselineAdjustment is not enough
			if(blockProgression != BlockProgression.RL)
				ulOffset += (stOffset - baseSTAdjustment) + metrics.underlineThickness/2;
			else
			{	
				var para:ParagraphElement = this.getParagraph();

				if (para.computedFormat.locale.toLowerCase().indexOf("zh") == 0)
				{
					ulOffset = -ulOffset;
					ulOffset -= (stOffset - baseSTAdjustment + (metrics.underlineThickness*2));
				}
				else
					ulOffset -= (-ulOffset + stOffset + baseSTAdjustment + (metrics.underlineThickness/2));
			}
			
			return ulOffset;
		}
		
		/** @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," fte:"+getDebugIdentity(_blockElement)+" "+extraData);
			
			// TODO: eventually these tests will be valid for InlineGraphicElement elements as well
			if (!(this is InlineGraphicElement))
			{
				rslt += assert(textLength != 0 || bindableElement || (parent is SubParagraphGroupElementBase && parent.numChildren == 1), "FlowLeafElement with zero textLength must be deleted"); 
				rslt += assert(parent is ParagraphElement || parent is SubParagraphGroupElementBase, "FlowLeafElement must have a ParagraphElement or SubParagraphGroupElementBase parent");
			}
			return rslt;
		}
	}
}
