////////////////////////////////////////////////////////////////////////////////
//
//  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.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();
			}
			else if (changeType == ModelChange.ELEMENT_REMOVAL)
			{
				if (this.hasActiveEventMirror())
					tf.decInteractiveObjectCount();
			}
			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);
		}
		
		/** @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				= 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;
		}
	}
}
