////////////////////////////////////////////////////////////////////////////////
//
//  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.compose
{
	import flash.display.DisplayObject;
	import flash.display.GraphicsPathCommand;
	import flash.display.GraphicsPathWinding;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.engine.TextBlock;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextLineValidity;
	import flash.text.engine.TextRotation;
	import flash.utils.Dictionary;
	
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.edit.SelectionFormat;
	import flashx.textLayout.elements.ContainerFormattedElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.FlowValueHolder;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.SubParagraphGroupElement;
	import flashx.textLayout.elements.TCYElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.external.WeakRef;
	import flashx.textLayout.formats.BackgroundColor;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Direction;
	import flashx.textLayout.formats.Float;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.JustificationRule;
	import flashx.textLayout.formats.LeadingModel;
	import flashx.textLayout.formats.LineBreak;
	import flashx.textLayout.formats.TextDecoration;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.CharacterUtil;
	
	use namespace tlf_internal;
	
	
	/** 
	 * The TextFlowLine class represents a single line of text in a text flow.
	 * 
	 * <p>Use this class to access information about how a line of text has been composed: its position, 
	 * height, width, and so on. When the text flow (TextFlow) is modified, the lines immediately before and at the  
	 * site of the modification are marked as invalid because they need to be recomposed. Lines after
	 * the site of the modification might not be damaged immediately, but they might be regenerated once the
	 * text is composed. You can access a TextFlowLine that has been damaged, but any values you access
	 * reflect the old state of the TextFlow. When the TextFlow is recomposed, it generates new lines and you can 
	 * get the new line for a given position by calling <code>TextFlow.flowComposer.findLineAtPosition()</code>.</p>
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	 
	public final class TextFlowLine implements IVerticalJustificationLine 
	{

		 
		
		/** @private */
				
		private var _absoluteStart:int;		// text-offset of start of line - from beginning of the TextFlow
		private var _textLength:int;	// number of chars to next line (incl trailing spaces, etc.)
		private var _height:Number = 0;		// y advance
		private var _spaceBefore:Number = 0;	// amount of vertical space to leave at the top of the line
		private var _spaceAfter:Number = 0;	// amount of vertical space to leave at the bottom of the line
		private var _x:Number = 0;			// left edge of line
		private var _y:Number = 0;			// top edge of line
		private var _outerTargetWidth:Number = 0; // width line is composed to, excluding indents
		private var _para:ParagraphElement;			// owning paragraph
		private var _controller:ContainerController;	// what frame the line was composed into
		private var _columnIndex:int;			// column number in the container
		
		private var _adornCount:int = 0;
		
		// added to support TextFlowLine when TextLine not available
		private var _ascent:Number;
		private var _descent:Number;
		private var _targetWidth:Number;
		private var _validity:String;
		private var _unjustifiedTextWidth:Number;
		private var _textWidth:Number;
		private var _textHeight:Number;
		private var _lineOffset:Number;
		private var _released:Boolean;	// True if line has been released from the TextBlock
		
		private var _textLineCache:WeakRef;
		
		 /**
		 * The height of the text line, which is equal to <code>ascent</code> plus <code>descent</code>. The 
		 * value is calculated based on the difference between the baselines that bound the line, either 
		 * ideographic top and bottom or ascent and descent depending on whether the baseline at y=0 
		 * is ideographic (for example, TextBaseline.IDEOGRAPHIC_TOP) or not. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flash.text.engine.TextBaseline TextBaseline
	 	 */
		
		public function get textHeight():Number 
		{ return _textHeight; }
		
		/** @private - the selection block cache */
		static private var _selectionBlockCache:Dictionary = new Dictionary(true);
		
		private static const EMPTY_LINE_WIDTH:Number = 2;		// default size of empty line selection

		/** Constructor - creates a new TextFlowLine instance. 
		 *  <p><strong>Note</strong>: No client should call this. It's exposed for writing your own composer.</p>
		 *
		 * @param textLine The TextLine display object to use for this line.
		 * @param paragraph The paragraph (ParagraphElement) in which to place the line.
		 * @param outerTargetWidth The width the line is composed to, excluding indents.
		 * @param lineOffset The line's offset in pixels from the appropriate container inset (as dictated by paragraph direction and container block progression), prior to alignment of lines in the paragraph. 
		 * @param absoluteStart	The character position in the text flow at which the line begins.
		 * @param numChars	The number of characters in the line.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flash.text.engine.TextLine
	 	 * @see flashx.textLayout.elements.ParagraphElement
	 	 * @see #absoluteStart
	 	 */
	 	 
		public function TextFlowLine(textLine:TextLine, paragraph:ParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0)
		{
			initialize(paragraph, outerTargetWidth, lineOffset, absoluteStart,numChars,textLine);		
		}
		
		/** @private */
		tlf_internal function initialize(paragraph:ParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0, textLine:TextLine = null):void
		{
			_para = paragraph;
			_outerTargetWidth = outerTargetWidth;
			_absoluteStart = absoluteStart;
			_textLength = numChars;
			_released = (textLine == null);
			if (textLine)
			{
				_textLineCache = new WeakRef(textLine);
				textLine.userData = this;
				_targetWidth = textLine.specifiedWidth;
				_ascent = textLine.ascent;
				_descent = textLine.descent;
				_unjustifiedTextWidth = textLine.unjustifiedTextWidth;
				_textWidth = textLine.textWidth;
				_textHeight = textLine.textHeight;
				_lineOffset = lineOffset;
				_validity = TextLineValidity.VALID;
			}
			else 
				_validity = TextLineValidity.INVALID;
		}
		
		/** @private */
		tlf_internal function releaseTextLine():void
		{ _textLineCache = null; }

		/** @private */
		tlf_internal function peekTextLine():TextLine
		{ return _textLineCache ? _textLineCache.get() : null; }
				
		/** 
		 * The horizontal position of the line relative to its container, expressed as the offset in pixels from the 
		 * left of the container.
		 * <p><strong>Note: </strong>Although this property is technically <code>read-write</code>, 
		 * you should treat it as <code>read-only</code>. The setter exists only to satisfy the
		 * requirements of the IVerticalJustificationLine interface that defines both a getter and setter for this property.
		 * Use of the setter, though possible, will lead to unpredictable results.
		 * </p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see #y
		 */
		public function get x():Number
		{ return _x; }
		
		/** 
		 * This comment is ignored, but the setter should not be used and exists only to satisfy
		 * the IVerticalJustificationLine interface.
		 * @see flashx.textLayout.compose.IVerticalJustificationLine 
		 * @private 
		 */
		public function set x(lineX:Number):void
		{ _x = lineX; }
		
		/** 
		 * The vertical position of the line relative to its container, expressed as the offset in pixels from the top 
		 * of the container.
		 * <p><strong>Note: </strong>Although this property is technically <code>read-write</code>, 
		 * you should treat it as <code>read-only</code>. The setter exists only to satisfy the
		 * requirements of the IVerticalJustificationLine interface that defines both a getter and setter for this property.
		 * Use of the setter, though possible, will lead to unpredictable results.
		 * </p>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 * 
	 	 * @see #x
		 */
		public function get y():Number
		{ return _y; }
		
		/** This comment is ignored, but the setter should not be used and exists only to satisfy
		 * the IVerticalJustificationLine interface.
		 * @see flashx.textLayout.compose.IVerticalJustificationLine
		 * @private
		 */
		public function set y(lineY:Number):void
		{ _y = lineY; }
		
		/** @private */
		tlf_internal function setXYAndHeight(lineX:Number,lineY:Number,lineHeight:Number):void
		{
			_x = lineX;
			_y = lineY;
			_height = lineHeight
		}
		
		/** 
		 * One of the values from TextFlowLineLocation for specifying a line's location within a paragraph.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flashx.textLayout.elements.ParagraphElement
	 	 * @see TextFlowLineLocation
		 */
		 
		public function get location():int
		{
			if (_para)
			{
				var lineStart:int = _absoluteStart - _para.getAbsoluteStart();
				
				// Initialize settings for location
				if (lineStart == 0)		// we're at the start of the paragraph
					return _textLength == _para.textLength ? TextFlowLineLocation.ONLY : TextFlowLineLocation.FIRST;
				if (lineStart + _textLength == _para.textLength)	// we're at the end of the para
					return TextFlowLineLocation.LAST;
			}
			return TextFlowLineLocation.MIDDLE;
		}
		
		/** 
		 * The controller (ContainerController object) for the container in which the line has been placed.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 * 
	 	 * @see flashx.textLayout.container.ContainerController 
		 */
		 
		public function get controller():ContainerController
		{ return _controller; }
		
		/** The number of the column in which the line has been placed, with the first column being 0.
		 *		
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	 
		public function get columnIndex():int
		{ return _columnIndex; }
		
		/** @private */
		tlf_internal function setController(cont:ContainerController,colNumber:int):void
		{ 
			_controller = cont as ContainerController;
			_columnIndex = colNumber;
		}
		
		/** The height of the line in pixels.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 */
		 
		public function get height():Number
		{ return _height; }
		
		/** 
		 * @copy flash.text.engine.TextLine#ascent
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		 
		public function get ascent():Number
		{ return _ascent; }
		
		/** 
		 * @copy flash.text.engine.TextLine#descent
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		 
		public function get descent():Number
		{ return _descent; }
		
		/** 
		 * The line's offset in pixels from the appropriate container inset (as dictated by paragraph direction and container block progression), 
		 * prior to alignment of lines in the paragraph.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function get lineOffset():Number
		{
			return _lineOffset;
		}
		
				
		/** 
		 * The paragraph (ParagraphElement) in which the line resides.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 * 
	 	 * @see flashx.textLayout.elements.ParagraphElement
	 	 */
	 	 
		public function get paragraph():ParagraphElement
		{ return _para; }
		
		/** 
		 * The location of the line as an absolute character position in the TextFlow object.
		 * 
		 * @return 	the character position in the text flow at which the line begins.
		 *
		 * @playerversion Flash 10
	 	 * @playerversion AIR 1.5
	 	 * @langversion 3.0
 		 *
 		 * @see flashx.textLayout.elements.TextFlow
		 */
		 
		public function get absoluteStart():int
		{ return _absoluteStart; }
		/** @private */
		tlf_internal function setAbsoluteStart(val:int):void
		{ _absoluteStart = val; }
				
		/** 
		 * The number of characters to the next line, including trailing spaces. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	
		public function get textLength():int
		{ return _textLength; }
		/** @private */
		tlf_internal function setTextLength(val:int):void
		{ 
			_textLength = val; 
		//	assert(_validity == TextLineValidity.INVALID, "not already damaged");
			damage(TextLineValidity.INVALID);
		}
		
		/** 
		 * The amount of space to leave before the line.
		 * <p>If the line is the first line of a paragraph that has a space-before applied, the line will have
		 * a <code>spaceBefore</code> value. If the line comes at the top of a column, <code>spaceBefore</code> is ignored. 
		 * Otherwise, the line follows another line in the column, and it is positioned vertically to insure that there is
		 * at least this much space left between this line and the last line of the preceding paragraph.</p> 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flashx.textLayout.formats.TextLayoutFormat#paragraphSpaceBefore TextLayoutFormat.paragraphSpaceBefore
		 */
		 
		public function get spaceBefore():Number
		{ return _spaceBefore; }
		/** @private */
		tlf_internal function setSpaceBefore(val:Number):void
		{ _spaceBefore = val; }
		
		/** 
		 * The amount of space to leave after the line.
		 * <p>If the line is the last line of a paragraph that has a space-after, the line will have
		 * a <code>spaceAfter</code> value. If the line comes at the bottom of a column, then the <code>spaceAfter</code>
		 * is ignored. Otherwise, the line comes before another line in the column, and the following line must be positioned vertically to
		 * insure that there is at least this much space left between this last line of the paragraph and the first
		 * line of the following paragraph.</p> 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 * @see flashx.textLayout.formats.TextLayoutFormat#paragraphSpaceAfter TextLayoutFormat.paragraphSpaceAfter
		 */
		 
		public function get spaceAfter():Number
		{ return _spaceAfter; }
		/** @private */
		tlf_internal function setSpaceAfter(val:Number):void
		{ _spaceAfter = val; }
		
		/** @private 
		 * Target width not including paragraph indents @private */
		 
		tlf_internal function get outerTargetWidth():Number
		{ return _outerTargetWidth; }
		
		/** @private */
		tlf_internal function set outerTargetWidth(val:Number):void
		{ _outerTargetWidth = val; }
		
		/** @private  
		 * Amount of space used to break the line
		 * <p>The target width is the amount of space allowed for the line, including the space required for indents.</p>
		 */
		tlf_internal function get targetWidth():Number
		{ return _targetWidth; }
										
		/** 
		 * Returns the bounds of the line as a rectangle.
		 *
		 * @return a rectangle that represents the boundaries of the line.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		 
		public function getBounds():Rectangle
		{	
			var textLine:TextLine = getTextLine(true);
			if (!textLine)
				return new Rectangle();

			// TODO: just use the textLine.x and textLine.y - after all getTextLine now sets them.
			// not going to change this right now though
			var bp:String = paragraph.getAncestorWithContainer().computedFormat.blockProgression;
			var shapeX:Number = createShapeX();
			var shapeY:Number = createShapeY(bp);
			if (bp == BlockProgression.TB)
				shapeY += descent-textLine.height;
			return new Rectangle(shapeX, shapeY, textLine.width, textLine.height);			
		}
								
		/** The validity of the line. 
		 * <p>A line can be invalid if the text, the attributes applied to it, or the controller settings have
		 * changed since the line was created. An invalid line can still be displayed, and you can use it, but the values
		 * used will be the values at the time it was created. The line returned by <code>getTextLine()</code> also will be in an
		 * invalid state. </p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see #getTextLine()
	 	 * @see flash.text.engine.TextLine#validity TextLine.validity
	 	 * @see FlowDamageType#GEOMETRY
		 */
		 
		public function get validity():String
		{ 
			// A TextLine may be invalidated separately from the TextFlowLine, when the invalidation is driven from the Player (e.g. changes have been made directly). 
			// If the TextFlowLine is marked valid, the line may still be invalid if the TextLine has been marked invalid.
			// If the line has been released (TextBlock.releaseLines called), then it may have an existing TextLine that got marked invalid by the Player 
			// when it was released. We want to ignore that invalid marking.
			if (!_released)
			{
				var textLine:TextLine = peekTextLine();
				if (textLine && (_validity == FlowDamageType.GEOMETRY || _validity == TextLineValidity.VALID) && textLine.validity != TextLineValidity.VALID)
					_validity = textLine.validity;
			}
			return _validity; 
		}
		
		/** 
		 * The width of the line if it was not justified. For unjustified text, this value is the same as <code>textLength</code>. 
		 * For justified text, this value is what the length would have been without justification, and <code>textLength</code> 
		 * represents the actual line width. For example, when the following String is justified and assigned a width of 500, it 
		 * has an actual width of 500 but an unjustified width of 268.9921875. 
		 *
		 * @internal TBD: add graphic of justified line
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		 
		public function get unjustifiedTextWidth():Number
		{ 
			// hack - outerTargetWidth holds value from the factory
			return _unjustifiedTextWidth + (_outerTargetWidth - targetWidth); 
		}
		
		/** @private 
		 * True if the line needs composing. */
		tlf_internal function isDamaged():Boolean
		{ 
			if (_validity != TextLineValidity.VALID)
				return true;
			if (!_released)
			{
				var textLine:TextLine = peekTextLine(); 
				if (textLine && textLine.validity != TextLineValidity.VALID)
					return true;
			}
			return false;
		}
		
		/** @private
		 * Mark the line as valid */
		tlf_internal function clearDamage():void
		{ 
			CONFIG::debug { assert(_validity == FlowDamageType.GEOMETRY, "can't clear damage other than geometry"); }
			if (_validity == TextLineValidity.VALID)		// already is valid
				return;	
			_validity = TextLineValidity.VALID; 
			
			//CONFIG::debug { assert(_textLineCache != null, "bad call to clearDamage"); }

			var textLine:TextLine =  peekTextLine();

			// The line in the cache, if there is one, is either invalid because its been released, or its geometry_damaged, or its already valid.
			CONFIG::debug { assert(!textLine || _released || textLine.validity == TextLineValidity.VALID || textLine.validity == FlowDamageType.GEOMETRY, "can't clear TextLine damage other than geometry"); }

			if (textLine && !_released)	// mark the TextLine as well
			{
				textLine.validity = TextLineValidity.VALID;
				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",TextLineValidity.VALID);  }
			}
		}
		
		/** @private
		 * Mark the line as damaged */
		 
		tlf_internal function damage(damageType:String):void
		{
			// trace("TextFlowLine.damage ", this.start.toString(), this.textLength.toString());
			if (_validity == damageType || _validity == TextLineValidity.INVALID)
				return;	// totally damaged
			_validity = damageType;
			
			var textLine:TextLine = peekTextLine();
			if (textLine && textLine.validity != TextLineValidity.INVALID)
			{
				textLine.validity = _validity;
				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",damageType);  }
			}
		}
		
		/** @private */
		CONFIG::debug public function toString():String
		{
			return "x:" + x + " y: " + y + " absoluteStart:" + absoluteStart + " textLength:" + textLength +  " location: " + location + " validity: " + _validity;
		}
	
		/** 
		 * Indicates whether the <code>flash.text.engine.TextLine</code> object for this TextFlowLine exists.  
		 * The value is <code>true</code> if the TextLine object has <em>not</em> been garbage collected and 
		 * <code>false</code> if it has been.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
	 	 * @see flash.text.engine.TextLine TextLine
		 */
		 
		public function get textLineExists():Boolean
		{
			return peekTextLine() != null;			
		}

		/** 
		 * Returns the <code>flash.text.engine.TextLine</code> object for this line, which might be recreated 
		 * if it does not exist due to garbage collection. Set <code>forceValid</code> to <code>true</code>
		 * to cause the TextLine to be regenerated. Returns null if the TextLine cannot be recreated.
		 *.
		 * @param forceValid	if true, the TextLine is regenerated, if it exists but is invalid.
		 *
		 * @return object for this line or <code>null</code> if the TextLine object cannot be 
		 * recreated.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flash.text.engine.TextLine TextLine
		 */
		 
		public function getTextLine(forceValid:Boolean = false):TextLine
		{ 				
			var textLine:TextLine = peekTextLine();
			if (!textLine || (textLine.validity != TextLineValidity.VALID && forceValid))
			{
				if (isDamaged() && validity != FlowDamageType.GEOMETRY)
					return null;
				
				var textBlock:TextBlock = paragraph.getTextBlock();

				// regenerate the whole paragraph at once, up to current position. The TextBlock may already contain valid
				// lines that got generated on a prior call to getTextLine but couldn't be added to the cache (e.g., because
				// the cache contains an invalid line that is in the display list), so we check for that before making a new line.
				var previousLine:TextLine;
				var currentLine:TextLine = textBlock.firstLine;
				var flowComposer:IFlowComposer = paragraph.getTextFlow().flowComposer;
				var lineIndex:int = flowComposer.findLineIndexAtPosition(paragraph.getAbsoluteStart());
				do
				{
					var line:TextFlowLine = flowComposer.getLineAt(lineIndex);
					CONFIG::debug { assert (line.paragraph == paragraph, "Expecting line in same paragraph"); }
					if (currentLine != null && currentLine.validity == TextLineValidity.VALID)
					{
						textLine = currentLine;
						currentLine = currentLine.nextLine;
						
						line.updateTextLineCache(textLine);
					}
					else
					{
						textLine = line.recreateTextLine(textBlock, previousLine);
						currentLine = null;
					}
					previousLine = textLine;
					++lineIndex;
				} while (line != this);			
			}
			
			if(textLine != null && textLine.numChildren == 0 && _adornCount > 0)
			{
				var para:ParagraphElement = this.paragraph;
				var paraStart:int = para.getAbsoluteStart();
				var elem:FlowLeafElement = para.findLeaf(this.absoluteStart - paraStart);
				var elemStart:int = elem.getAbsoluteStart();
				
				createAdornments(para.getAncestorWithContainer().computedFormat.blockProgression,elem, elemStart);		
			}
			
			return textLine;
		}
		
		/** @private Regenerate the TextLine -- called when textLine has been gc'ed */
		tlf_internal function recreateTextLine(textBlock:TextBlock, previousLine:TextLine):TextLine
		{
			var textLine:TextLine;
			
			// If we already have a valid text line, just return it.
			if (!_released)
			{
				textLine = peekTextLine();
				if (textLine)
					return textLine;
			}
			
			var textFlow:TextFlow = paragraph.getTextFlow();
			var flowComposer:IFlowComposer = textFlow.flowComposer;
			var swfContext:ISWFContext = flowComposer.swfContext ? flowComposer.swfContext : BaseCompose.globalSWFContext;
			
			textLine = TextLineRecycler.getLineForReuse();
			if (textLine)
			{
				CONFIG::debug { assert(textFlow.backgroundManager == null || textFlow.backgroundManager.lineDict[textLine] === undefined,"Bad TextLine in recycler cache"); }
				textLine = swfContext.callInContext(textBlock["recreateTextLine"], textBlock, [ textLine, previousLine, _targetWidth, _lineOffset, true ]);
			}
			else
				textLine = swfContext.callInContext(textBlock.createTextLine, textBlock, [ previousLine, _targetWidth, _lineOffset, true ]);
			
			textLine.x = createShapeX();
			CONFIG::debug { Debugging.traceFTEAssign(textLine,"x", createShapeX());  }
			textLine.y = createShapeY(textFlow.computedFormat.blockProgression);
			CONFIG::debug { Debugging.traceFTEAssign(textLine,"y", createShapeY(textFlow.computedFormat.blockProgression));  }
			textLine.doubleClickEnabled = true;

			updateTextLineCache(textLine);
			
			return textLine;
		}
		
		/** the rule is that all "displayed" lines must be in the TextFlowLine textLineCache.  Put this new line in the cache iff there isn't already a displayed line */
		private function updateTextLineCache(textLine:TextLine):void
		{
			textLine.userData = this;	
			var existingTextLine:TextLine = peekTextLine();
			// If there is an existing, released line, and it is currently being displayed, we can't replace it in the cache.
			if (!existingTextLine || existingTextLine.parent == null)
			{
				if (existingTextLine != textLine)
					_textLineCache = new WeakRef(textLine);	
				_released = false;		
			}
		}
		
		/** @private */
		tlf_internal function markReleased():void
		{
			_released = true;
		}
		
		/** @private */
		tlf_internal function createShape(bp:String):TextLine
		{
			var textLine:TextLine = getTextLine();
			
			var newX:Number = createShapeX();
			//if (int(newX*20) != int(textLine.x*20))
			{
				textLine.x = newX;
				CONFIG::debug { Debugging.traceFTEAssign(textLine,"x", newX);  }
			}
			var newY:Number = createShapeY(bp);
			//if (int(newY*20) != int(textLine.y*20))
			{
				textLine.y = newY;
				CONFIG::debug { Debugging.traceFTEAssign(textLine,"y", newY);  }
			}
			return textLine;
		}
		
		private function createShapeX():Number
		{ return x; }
		
		private function createShapeY(bp:String):Number
		{ return bp == BlockProgression.RL ? y : y + _ascent; }
        
         /** @private 
         * Scan through the format runs within the line, and draw any underline or strikethrough that might need it
		 */
		 
		tlf_internal function createAdornments(blockProgression:String,elem:FlowLeafElement,elemStart:int):void
		{
			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to createAdornments"); } 
			var endPos:int = _absoluteStart + _textLength;
			
			//init adornments back to 0
			_adornCount = 0;

			for (;;)
			{
				var format:ITextLayoutFormat = elem.computedFormat;

				_adornCount += elem.updateAdornments(this, blockProgression);
				
				var fvh:FlowValueHolder = elem.format as FlowValueHolder;
				if(fvh && fvh.userStyles && fvh.userStyles.imeStatus)
				{
					elem.updateIMEAdornments(this, blockProgression, fvh.userStyles.imeStatus as String);
				}
				elemStart += elem.textLength;
				if (elemStart >= endPos)
					break;
				elem = elem.getNextLeaf(_para);
				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
			}
		}
        
       /** @private 
         * Scan through the format runs within the line, and figure out what the leading for the overall line is.
		 * The line's leading is equal to the maximum leading of any individual run within the line.
		 * The leading in an individual format run is calculated by looking at the leading attribute in the
		 * CharacterFormat. If it is set to a value, we just use that value. Otherwise, if it is set to AUTO,
		 * we calculate the leading based on the point size and the auto leading percentage from the ParagraphFormat.
		 */
		 
		tlf_internal function getLineLeading(bp:String,elem:FlowLeafElement,elemStart:int):Number
		{
			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getLineLeading"); } 
			var endPos:int = _absoluteStart + _textLength;
			var totalLeading:Number = 0;
			CONFIG::debug { assert(elem.getAncestorWithContainer() != null,"element with no container"); }
			for (;;)
			{
				//this is kinda bunk and really shouldn't be here, but I'm loath to find a better way....
				//ignore the leading on a TCY Block.
				//if the elem is in a TCYBlock, AND it is not the only block in the line, "skip" it
				if (!(bp == BlockProgression.RL && (elem.parent is TCYElement) &&  (!isNaN(totalLeading) || (elem.textLength != this.textLength))))
				{
					var elemLeading:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(elem.computedFormat.lineHeight,elem.getEffectiveFontSize());
					totalLeading = Math.max(totalLeading, elemLeading);
				}
				elemStart += elem.textLength;
				if (elemStart >= endPos)
					break;
				elem = elem.getNextLeaf(_para);
				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
			}
			return totalLeading;
		}
        
		/** @private 
		 * Scan through the format runs within the line, and figure out what the typographic ascent (i.e. ascent relative to the 
		 * Roman baseline) for the overall line is. Normally it is the distance between the Roman and Ascent baselines, 
		 * but it may be adjusted upwards by the width/height of the GraphicElement.
		 */
		tlf_internal function getLineTypographicAscent(elem:FlowLeafElement,elemStart:int):Number
		{
			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getLineTypographicAscent"); } 
			return getTextLineTypographicAscent(getTextLine(), elem, elemStart, absoluteStart+textLength, _para);
		}
        
		/** @private 
		 * Scan through the format runs within the line, and figure out what the typographic ascent (i.e. ascent relative to the 
		 * Roman baseline) for the overall line is. Normally it is the distance between the Roman and Ascent baselines, 
		 * but it may be adjusted upwards by the width/height of the GraphicElement.
		 */
		static tlf_internal function getTextLineTypographicAscent(textLine:TextLine, elem:FlowLeafElement,elemStart:int, textLineEnd:int, para:ParagraphElement):Number
		{
			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getTextLineTypographicAscent"); } 
			var rslt:Number = textLine.getBaselinePosition(flash.text.engine.TextBaseline.ROMAN) - textLine.getBaselinePosition(flash.text.engine.TextBaseline.ASCENT);
				
			for (;;) 
			{
				if (elem is InlineGraphicElement)
					rslt = Math.max(rslt,InlineGraphicElement(elem).getTypographicAscent(textLine));
				elemStart += elem.textLength;
				if (elemStart >= textLineEnd)
					break;
				elem = elem.getNextLeaf(para);
				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
			}
			return rslt;
		}
        
        //helper method to determine which subset of line is underlined
        //I believe this will be replaced by the eventSink mechanism
        private function isTextlineSubsetOfSpan(element:FlowLeafElement): Boolean
        { 
        	var spanStart:int = element.getAbsoluteStart();
        	var spanEnd:int = spanStart + element.textLength;
        	
        	var lineStart:int = this.absoluteStart;
        	var lineEnd:int = this.absoluteStart + this._textLength;
          	
        	return spanStart <= lineStart && spanEnd >= lineEnd;
        }
        
       
        
 		/** Create a rectangle for selection */
		static private function createSelectionRect(selObj:Shape, color:uint, x:Number, y:Number, width:Number, height:Number):DisplayObject
		{
 			selObj.graphics.beginFill(color);
 			var cmds:Vector.<int> = new Vector.<int>();
 			var pathPoints:Vector.<Number> = new Vector.<Number>();
 			
 			//set the start point - topLeft
 			cmds.push(GraphicsPathCommand.MOVE_TO);
 			pathPoints.push(x);
 			pathPoints.push(y);
 			
 			//line to topRight
 			cmds.push(GraphicsPathCommand.LINE_TO);
 			pathPoints.push(x + width);
 			pathPoints.push(y);
 			
 			//line to botRight
 			cmds.push(GraphicsPathCommand.LINE_TO);
 			pathPoints.push(x + width);
 			pathPoints.push(y + height);
 			
 			//line to botLeft
 			cmds.push(GraphicsPathCommand.LINE_TO);
 			pathPoints.push(x);
 			pathPoints.push(y + height);
 			
 			//line to close the path - topLeft
 			cmds.push(GraphicsPathCommand.LINE_TO);
 			pathPoints.push(x);
 			pathPoints.push(y);
 			
 			selObj.graphics.drawPath(cmds, pathPoints, flash.display.GraphicsPathWinding.NON_ZERO);
 			
			return selObj;			
		}
	
		/** @private getSelectionShapesCacheEntry
		 * 
		 * creates and adds block selection(s) to the text container.  In most circumstances,
		 * this method will produce and add a single DisplayObject, but in certain circumstances,
		 * such as TCY in TTB text, will need to make multiple selection rectangles.
		 * 
		 * Examples:
		 * 1) horizontal - ABCDE
		 * 2) vertical - ABCDE
		 * 3) horizontal - ABcdE
		 * 4) vertical:		A
		 * 					B
		 * 				   cde
		 * 					F
		 * 
		 */
		private function getSelectionShapesCacheEntry(begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine, blockProgression:String):SelectionCache
		{
			if (isDamaged())
				return null;
			
			// CONFIG::debug { assert(_textLineCache != null, "bad call to getSelectionShapesCacheEntry"); }
			
			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
			var paraAbsStart:int = _para.getAbsoluteStart();
			
			//if the indexes are identical and are equal to the start of the line, then
			//don't draw anything.  This prevents a bar being drawn on a following line when
			//selecting accross line boundaries
			//with exception for a selection that includes just the first character of an empty last line in the TextFlow
			if (begIdx == endIdx && paraAbsStart + begIdx == absoluteStart)
			{
				if (absoluteStart != _para.getTextFlow().textLength-1)
					return null;
				endIdx++;
			}
			
			//the cached selection bounds and rects
			var selectionCache:SelectionCache = _selectionBlockCache[this];
			if (selectionCache && selectionCache.begIdx == begIdx && selectionCache.endIdx == endIdx)
				return selectionCache;			
			
			var drawRects:Array = new Array();
			//an array to store any tcy rectangles which need separate processing and may not exist
			var tcyDrawRects:Array = new Array();
			
			if(selectionCache == null)
			{
				selectionCache = new SelectionCache();
				_selectionBlockCache[this] = selectionCache;
			}	
			else
			{
				selectionCache.clear();
			}
			selectionCache.begIdx = begIdx;
			selectionCache.endIdx = endIdx;
			
			var textLine:TextLine = getTextLine();
			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
			calculateSelectionBounds(textLine, drawRects, begIdx, endIdx, blockProgression, heightAndAdj);
			
			//iterate the blocks and create DisplayObjects to draw...
			for each(var drawRect:Rectangle in drawRects)
			{
				CONFIG::debug{ assert(selectionCache != null, "If we're caching, selectionArray should never be null!"); }
				//we have to make new rectangles or the convertLineRectToGlobal will alter the cached ones!
				selectionCache.pushSelectionBlock(drawRect);
			}
			

			//allow the atoms to be garbage collected.
			if (textLine)
				textLine.flushAtomData();
			
			return selectionCache;
		}
		
		
		/** @private - helper method to calculate all selection blocks within a line.*/
		tlf_internal function calculateSelectionBounds(textLine:TextLine, rectArray:Array, begIdx:int, endIdx:int, blockProgression:String, heightAndAdj:Array):void
		{
			//the direction of the text
			var direction:String = _para.computedFormat.direction;
			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
			var paraAbsStart:int = _para.getAbsoluteStart();
			//the current index.  used to iterate to the next element
			var curIdx:int = begIdx;
			//the current FlowLeafElement as determined by curIdx
			var curElem:FlowLeafElement = null;
			//the hightest glyph.  Needed to normalize the rectangles we'll be building
			var largestRise:Number = 0;
			
			//blockRectArray holds each leaf's blocks which could be 1 or more
			var blockRectArray:Array = new Array();
			//floatRectArray holds the selection rects for any floats in the range.
			var floatRectArray:Array = null;
			//tcyDrawRects:Array
			var tcyDrawRects:Array = null;
			
			//do this loop and only afterwards perform the normalization and addition to the rectArr
			while(curIdx < endIdx)
			{
				curElem = _para.findLeaf(curIdx);
				//if we somehow got a 0 length element, then increment the index and continue
				if(curElem.textLength == 0)
				{
					++curIdx;
					continue;
				}
				else if(curElem is InlineGraphicElement && (curElem as InlineGraphicElement).float != Float.NONE)
				{
					if(floatRectArray == null)
						floatRectArray = new Array();
						
					var tempFloatArray:Array = makeSelectionBlocks(curIdx, curIdx+1, paraAbsStart, blockProgression, direction, heightAndAdj);
					CONFIG::debug{ assert(tempFloatArray.length == 1, "How can a single floated InlineGraph have multiple shapes!"); }
					floatRectArray.push(tempFloatArray[0]);
					++curIdx;
					continue;
				}
				//the number of potential glyphs to hilite.  Could larger than needs be if we are only selecting part of it.
				var numCharsSelecting:int = curElem.textLength + curElem.getElementRelativeStart(_para) - curIdx;
				//the index of the last glyph to hilite.  If a partial selection, use endIdx
				var endPos:int = (numCharsSelecting + curIdx) > endIdx ? endIdx : (numCharsSelecting + curIdx);
				
				//if this is not a TCY in vertical, the blocks should all be running in the same direction
				if (blockProgression != BlockProgression.RL || 
					(textLine.getAtomTextRotation(textLine.getAtomIndexAtCharIndex(curIdx)) != TextRotation.ROTATE_0))
				{
					var leafBlockArray:Array = makeSelectionBlocks(curIdx, endPos, paraAbsStart, blockProgression, direction, heightAndAdj);
					//copy all the blocks into the blockRectArray - we'll normalize them later
					for(var leafBlockIter:int = 0; leafBlockIter < leafBlockArray.length; ++leafBlockIter)
					{
						blockRectArray.push(leafBlockArray[leafBlockIter]);
					}
				}
				else
				{
					var tcyBlock:FlowElement = curElem.getParentByType(TCYElement);
					CONFIG::debug{ assert(tcyBlock != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
					
					//if this element is still encompassed by a SubParagraphGroupElement of some kind (either a link or a TCYBlock)
                	//keep moving up to the parent.  Otherwise, the below code will go into an infinite loop.  bug 1905734
                	var tcyParentRelativeEnd:int = tcyBlock.parentRelativeEnd;
                	var subParBlock:SubParagraphGroupElement = tcyBlock.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
                	while (subParBlock)
                	{
                		tcyParentRelativeEnd += subParBlock.parentRelativeStart;
                		subParBlock = subParBlock.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
                	}
					
					var largestTCYRise:Number = 0;
                    var lastTCYIdx:int = endIdx < tcyParentRelativeEnd ? endIdx : tcyParentRelativeEnd;
                    var tcyRects:Array = new Array();

			
					while(curIdx < lastTCYIdx)
					{
						curElem = _para.findLeaf(curIdx);
						numCharsSelecting = curElem.textLength + curElem.getElementRelativeStart(_para) - curIdx;
						endPos = numCharsSelecting + curIdx > endIdx ? endIdx : numCharsSelecting + curIdx;
						var tcyRectArray:Array =  makeSelectionBlocks(curIdx, endPos, paraAbsStart, blockProgression, direction, heightAndAdj);
						
						for(var tcyBlockIter:int = 0; tcyBlockIter < tcyRectArray.length; ++tcyBlockIter)
						{
							var tcyRect:Rectangle = tcyRectArray[tcyBlockIter];
							
							if(tcyRect.height > largestTCYRise)
							{
								largestTCYRise = tcyRect.height;
							}
								
							tcyRects.push(tcyRect);
						}
						curIdx = endPos;
					}
					
					if(!tcyDrawRects)
						tcyDrawRects = new Array();
						
					normalizeRects(tcyRects, tcyDrawRects, largestTCYRise, BlockProgression.TB, direction);
					continue;
				
				}
				
				//set the curIdx to the last char in the block
				curIdx = endPos;
			}
			
			
			
			//adding check for an empty set of draw rects.  If there are not recangles, skip this.
			//this can happen is there are ONLY TCY blocks and the whole line is selected.
			//Watson 2273832. - gak 02.09.09
			//if the whole line is selected
			if(blockRectArray.length > 0 && (paraAbsStart + begIdx) == absoluteStart && (paraAbsStart + endIdx) == (absoluteStart + textLength))
			{
				curElem = _para.findLeaf(begIdx);
				//if we have the entire line selected, but the first element is NOT the last, then
				//we will land up with a selection which is 1 character wider than it should be.
				if(((curElem.getAbsoluteStart() + curElem.textLength) < (absoluteStart + textLength)) && endPos >= 2)
				{
					//make sure that this is a white char and that we aren't deselecting the last
					//char in a line - esp important for scripts which don't use spaces ie Japanese
					var charCode:int = _para.getCharCodeAtPosition(endPos - 1);
					if(charCode != SpanElement.kParagraphTerminator.charCodeAt(0) && CharacterUtil.isWhitespace(charCode))
					{
						var lastElemBlockArray:Array = makeSelectionBlocks(endPos - 1, endPos - 1, paraAbsStart, blockProgression, direction, heightAndAdj);
						var lastRect:Rectangle = lastElemBlockArray[lastElemBlockArray.length - 1];
						var modifyRect:Rectangle = blockRectArray[blockRectArray.length - 1] as Rectangle;
						
						if (blockProgression != BlockProgression.RL)
						{
							//if they have the same width, simply remove the last block
							if(modifyRect.width == lastRect.width)
							{
								blockRectArray.pop();
							}
							else
							{
								modifyRect.width -= lastRect.width;
								
								//if this is RTL, we need to shift the selection block over by the amount
								//we reduced it.
								if(direction == Direction.RTL)
									modifyRect.left -= lastRect.width;
							}
						}
						else
						{
							//if they have the same height, simply remove the last block
							if(modifyRect.height == lastRect.height)
							{
								blockRectArray.pop();
							}
							else
							{
								modifyRect.height -= lastRect.height;
								
								//if this is RTL, we need to shift the selection block down by the amount
								//we reduced it.
								if(direction == Direction.RTL)
									modifyRect.top += lastRect.height;
							}
						}
					}
				}
			}
			
			normalizeRects(blockRectArray, rectArray, largestRise, blockProgression, direction);
			//add in the TCY Rects
			if(tcyDrawRects && tcyDrawRects.length > 0)
			{
				for(var tcyIter:int = 0; tcyIter < tcyDrawRects.length; ++tcyIter)
				{
					rectArray.push(tcyDrawRects[tcyIter]);
				}
			}
			
			//float selections do not normalize, put them into the rect array now
			if(floatRectArray)
			{
				for(var floatIter:int = 0; floatIter < floatRectArray.length; ++floatIter)
				{
					rectArray.push(floatRectArray[floatIter]);
				}
			}
			
		}

		private function createSelectionShapes(selObj:Shape, selFormat:SelectionFormat, container:DisplayObject, begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):void
		{
			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
			CONFIG::debug { assert(contElement != null,"para with no container"); }
			var blockProgression:String = contElement.computedFormat.blockProgression;
			
			var selCache:SelectionCache = getSelectionShapesCacheEntry(begIdx, endIdx, prevLine, nextLine, blockProgression);
			if (!selCache)
				return;
		
			//iterate the blocks and create DisplayObjects to draw...
			var drawRect:Rectangle;
			var color:uint = selFormat.rangeColor;
			
			if (_para && _para.getTextFlow()) {
				var selMgr:ISelectionManager = _para.getTextFlow().interactionManager;
				if (selMgr && (selMgr.anchorPosition == selMgr.activePosition))
					color = selFormat.pointColor;
			}
			
			for each (drawRect in selCache.selectionBlocks)
			{
				drawRect = drawRect.clone();
				convertLineRectToContainer(drawRect, true);
				createSelectionRect(selObj, color, drawRect.x, drawRect.y, drawRect.width, drawRect.height);
			}
		}
		
 		/** @private 
		 * Get the height and vertical adjustment for the line's selection shape, assuming Western typographic rules
		 * where leading is included in selection.
		 * @return An array with two elements
		 * [0] height
		 * [1] vertical adjustment to counter 'align bottom' behavior. The remainder of the selection code assumes selection shape
		 * bottom is to be aligned with line descent. If this is not the case, vertical adjustment is set to an appropriate non-zero value. 
		 */
 		tlf_internal function getRomanSelectionHeightAndVerticalAdjustment (prevLine:TextFlowLine, nextLine:TextFlowLine):Array
 		{	
 			var rectHeight:Number = 0;
 			var verticalAdj:Number = 0; //  Default to 'align bottom'.
 			
			//This code erroneously assumed that it would only be called with a SPACE justifier and that AUTO would be up.  That is incorrect
			//because some scripts, like Korean, use an up leading model and the EAST_ASIAN justifier.  New code just performs the check
 			if(ParagraphElement.useUpLeadingDirection(_para.getEffectiveLeadingModel()))
 			{			
 				// "Space above, align bottom" 
 				// 1) Space above as dictated by first baseline offset for the first line or line leading otherwise (both obtained from the 'height' data member)
 				// 2) Selection rectangle must at least include all of the text area
 				rectHeight = height > _textHeight ? height : _textHeight;
 				
 				// 3) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
 			}
 			else
 			{
 				// TODO-9/4/08-Is this the right way to check for first/last lines? 
				var isFirstLine:Boolean = !prevLine || prevLine.controller != controller || prevLine.columnIndex != columnIndex;
				var isLastLine:Boolean  = !nextLine || nextLine.controller != controller || nextLine.columnIndex != columnIndex
						|| nextLine.paragraph.getEffectiveLeadingModel() == LeadingModel.ROMAN_UP;
 					//I'm removing this line as it makes the assumption that AUTO leading dir is UP only for Roman text, which is incorrect.
 					//Korean also uses UP leading but uses the EastAsian justifier. - gak 01.22.09
 					//||(nextLine.paragraph.computedFormat.leadingDirection == LeadingDirection.AUTO && nextLine.paragraph.computedFormat.justificationRule == JustificationRule.SPACE); 

 				if (isLastLine)
 				{
 					// There is no line after this one, or there is one which uses leading UP, so leading DOWN does not apply
 							
 					if (!isFirstLine)
 					{
 						// "Space above None, align bottom" (eqivalently, "Space below None, align top"): 
 						// 1) Only the text area should be selected
 						rectHeight = _textHeight;
 		
 						// 2) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
 					}
 					else
 					{
 						// "Space above, align bottom" 
 						// 1) Space above as dictated by first baseline offset 
 						// 2) Selection rectangle must at least include all of the text area
 						rectHeight = height > _textHeight ? height : _textHeight;
 						// 3) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
 					}
 				}
 				else
 				{
 					 // There is a line after this one, so leading DOWN applies
 					 
 					if (!isFirstLine)
 					{
 						// "Space below, align top" 
 						// 1) Space below as dictated by line leading (obtained from 'height' member of next line) 
 						// 2) Selection rectangle must at least include all of the text area
 						rectHeight = nextLine.height > _textHeight ? nextLine.height : _textHeight;
 						
 						// 3) Selection rectangle's top to be aligned with line ascent, so its bottom to be at rectHeight - textLine.ascent,
 						// not textLine.descent, set verticalAdj accordingly 
 						verticalAdj = rectHeight - _textHeight; // same as rectHeight - textLine.ascent - textLine.descent
 					}
 					else
 					{
 						// Union of 
 						// 1) first line, leading up: In this case, rectangle height is the larger of line height and text height,
 						// and the rectangle is shifted down by descent amount to align bottoms. So, top of rectangle is at:
 						var top:Number = _descent - (height > _textHeight ? height : _textHeight);
 						
 						// 2) interior line, leading down: In this case, rectangle height is the larger of line leading and text height,
 						// and the rectangle is shifted up by ascent amount to align tops. So, bottom of rectangle is at:
 						var bottom:Number = (nextLine.height > _textHeight ? nextLine.height : _textHeight) - _ascent;
 						
 						rectHeight = bottom - top;
 						
 						// 3) Selection rectangle's bottom to be at 'bottom', not the line's descent; set verticalAdj accordingly
 						verticalAdj = bottom - _descent;
 					}
 				}
 			}
 			
 			//If we don't have a line above us, then we need to pad the line a bit as well as make it shift up.
 			//If we don't, then it overlaps the line below too much OR clips the top of the glyphs.
 			if(!prevLine || prevLine.columnIndex != this.columnIndex || prevLine.controller != this.controller)
 			{
 				//make it taller - this is kinda a fudge, but we have no info to determine a good top.
 				//if we don't do this, the selection rectangle will clip to the top of the glyphs and even
 				//let parts stick out a bit.  So, re-add the descent and offset the rect by 50% so that
 				//it appears to balance the top and bottom.
 				rectHeight += this.descent;
 				verticalAdj = Math.floor(this.descent/2);
 			}
 			return [rectHeight, verticalAdj];
 		}
		
		/** @private 
		 * 
		 * 
		 */
		 private function makeSelectionBlocks(begIdx:int, endIdx:int, paraAbsStart:int, blockProgression:String, direction:String, heightAndAdj:Array):Array
		 {
		 	CONFIG::debug{ assert(begIdx <= endIdx, "Selection indexes are reversed!  How can this happen?!"); }
		 	
		 	var blockArray:Array = new Array();
		 	var blockRect:Rectangle = new Rectangle();
		 	var startElem:FlowLeafElement = _para.findLeaf(begIdx);
			var startMetrics:Rectangle = startElem.getComputedFontMetrics().emBox;
			
			var textLine:TextLine = getTextLine(true);

			//++makeBlockPassCounter;
		 	//trace(makeBlockPassCounter + ") direction = " + direction + " blockProgression = " + blockProgression);
				 	
		 	//if this is the whole line, then we should use line data to perform the selection
			if(paraAbsStart + begIdx == absoluteStart && paraAbsStart + endIdx == absoluteStart + textLength)
			{
				var globalStart:Point = new Point(0,0);
				var justRule:String = _para.getEffectiveJustificationRule();
				
				//use the textLine info if we're not using J justification
				if(justRule != JustificationRule.EAST_ASIAN)
				{
					if(blockProgression == BlockProgression.RL)
					{
						globalStart.x -= heightAndAdj[1];
						blockRect.width = heightAndAdj[0];
						blockRect.height = textLine.textWidth == 0 ? EMPTY_LINE_WIDTH : textLine.textWidth;
					}
					else 
					{
						globalStart.y += heightAndAdj[1];
						blockRect.height = heightAndAdj[0];
						blockRect.width = textLine.textWidth == 0 ? EMPTY_LINE_WIDTH : textLine.textWidth;
					}	
					
				}
				else
				{
					var eaStartElem:int  = textLine.getAtomIndexAtCharIndex(begIdx);
					var eaStartRect:Rectangle = textLine.getAtomBounds(eaStartElem);
					
					if(blockProgression == BlockProgression.RL)
					{
						blockRect.width = eaStartRect.width;
						blockRect.height = textLine.textWidth;
					}
					else
					{
						blockRect.height =  eaStartRect.height;
						blockRect.width = textLine.textWidth;
					}
				}
				
				blockRect.x = globalStart.x;
				blockRect.y = globalStart.y;
				
				if(blockProgression == BlockProgression.RL)
				{
					blockRect.x -= textLine.descent;
				}
				else
				{
					blockRect.y += (textLine.descent - blockRect.height)
				}
				
				//handle rotation
				if(startElem.computedFormat.textRotation == TextRotation.ROTATE_180 || 
					startElem.computedFormat.textRotation == TextRotation.ROTATE_90)
				{
					if(blockProgression != BlockProgression.RL)
						blockRect.y += blockRect.height / 2;
					else
						blockRect.x -= blockRect.width;
				}
				//push it onto array
				blockArray.push(blockRect);
			}
			else //we only have part of the line.  Get the start and end TC bounds
			{
				//trace(makeBlockPassCounter + ") begIdx = " + begIdx.toString() + " endIdx = " +  endIdx.toString());
				var begElementIndex:int = textLine.getAtomIndexAtCharIndex(begIdx); 
				var endElementIndex:int = adjustEndElementForBidi(begIdx, endIdx, begElementIndex, direction);
				
				//trace(makeBlockPassCounter + ") begElementIndex = " + begElementIndex.toString() + " endElementIndex = " +  endElementIndex.toString());
				CONFIG::debug{ assert(begElementIndex >= 0, "Invalid start index! begIdx = " + begIdx)};
				CONFIG::debug{ assert(endElementIndex >= 0, "Invalid end index! begIdx = " + endIdx)};
				
				if(direction == Direction.RTL && textLine.getAtomBidiLevel(endElementIndex)%2 != 0)
				{
					//if we are in RTL, anchoring the LTR text gets tricky.  Because the endElement is before the first
					//element - which is why we're in this code - the result can be a zero-width rectangle if the span of LTR
					//text breaks across line boundaries.  If that is the case, then the endElementIndex value will be 0.  As
					//this is the less common case, assume that it isn't and make all other cases come first
					if (endElementIndex == 0 && begIdx < endIdx-1)
					{
						//since the endElementIndex is 0, meaning that the LTR spans lines,
						//we want to grab the glyph before the endIdx which represents the last LTR glyph for the selection. 
						//Make a recursive call into makeSelectionBlocks using and endIdx decremented by 1.
						blockArray = makeSelectionBlocks(begIdx, endIdx - 1, paraAbsStart, blockProgression, direction, heightAndAdj);
						var bidiBlock:Array = makeSelectionBlocks(endIdx - 1, endIdx - 1, paraAbsStart, blockProgression, direction, heightAndAdj)
						var bidiBlockIter:int = 0;
						while(bidiBlockIter < bidiBlock.length)
						{
							blockArray.push(bidiBlock[bidiBlockIter]);
							++bidiBlockIter;
						}
						return blockArray;
					}
				}
				
				var begIsBidi:Boolean = begElementIndex != -1 ? isAtomBidi(begElementIndex, direction) : false;
				var endIsBidi:Boolean = endElementIndex != -1 ? isAtomBidi(endElementIndex, direction) : false;
				
			 	//trace("begElementIndex is bidi = " + begIsBidi.toString());
				//trace("endElementIndex is bidi = " + endIsBidi.toString());	
				
				if(begIsBidi || endIsBidi)
				{	
					//this code needs to iterate over the glyphs starting at the begElementIndex and going forward.
					//It doesn't matter is beg is bidi or not, we need to find a boundary, create a rect on it, then proceded.
					//use the value of begIsBidi for testing the consistency of the selection.
					
					//Example bidi text.  Note that the period comes at the left end of the line:
					//
					//	Bidi state:		f f t t t t t	(true/false)
					//	Element Index:0 1 2 3 4 5 6		(0 is the para terminator)
					//	Chars:			. t o _ b e
					//  Flow Index:	   6 0 1 2 3 4 (5) 	Note that these numbers represent the space between glyphs AND
					//					 5(f)			that index 5 is both the space after the e and before the period.
					//									but, the position 5 is not a valid cursor location.
					
					//the original code I implemented used the beg and endElement indexes however that fails because when the text
					//is mixed bidi/non-bidi, the indexes are only 1 char apart. This resulted in, for example, only the period in 
					//a line getting selected when the text was bidi.   Instead, we're going to use the begIdx and endIdx and 
					//recalculate the element indexes each time.  This is expensive, but I don't see an alternative. - gak 09.05.08
					var curIdx:int = begIdx;
					var incrementor:int = (begIdx != endIdx ? 1 : 0);
					
					//the indexes used to draw the seleciton.  activeStart/End represent the
					//beginning of the selection shape atoms, while cur is the one we are testing.
					var activeStartIndex:int = begElementIndex;
					var activeEndIndex:int = begElementIndex;
					var curElementIndex:int = begElementIndex;
					
					//when activeEndIsBidi no longer matches the bidi setting for the activeStartIndex, we will create the shape
					var activeEndIsBidi:Boolean = begIsBidi;
					
					do
					{
						//increment the index
						curIdx += incrementor;
						//get the next atom index
						curElementIndex = textLine.getAtomIndexAtCharIndex(curIdx);
						
						//calculate the bidi level for the - kinda cludgy, but if the bidi-text wraps, curElementIndex == -1
						//so just set it to false if this is the case.  It will get ignored in the subsequent check and curIdx
						//will == endIdx as this is the last glyph in the line - which is why the next is -1 - gak 09.12.08
						var curIsBidi:Boolean = (curElementIndex != -1) ? isAtomBidi(curElementIndex, direction) : false;
							
						if(curElementIndex != -1 && curIsBidi != activeEndIsBidi)
						{
							blockRect = makeBlock(activeStartIndex, activeEndIndex, startMetrics, blockProgression, direction, heightAndAdj);
							blockArray.push(blockRect);
							
							//shift the activeStart/End indexes to the current
							activeStartIndex = curElementIndex;
							activeEndIndex = curElementIndex;
							//update the bidi setting
							activeEndIsBidi = curIsBidi;
						}
						else
						{
							//we don't get another chance to make a block, so if this is the last char, make the block before we bail out.
							//we have to check both equality and equality plus the incrementor because if we don't, then we'll miss a
							//character in the selection.
							if(curIdx == endIdx)
							{
								blockRect = makeBlock(activeStartIndex, activeEndIndex, startMetrics, blockProgression, direction, heightAndAdj);
								blockArray.push(blockRect);
							}
							
							activeEndIndex = curElementIndex;
						}
					}while(curIdx < endIdx)
					
				}
				else
				{
					var testILG:InlineGraphicElement = startElem as InlineGraphicElement;
					if(!testILG || testILG.float == Float.NONE)
					{
						blockRect = makeBlock(begElementIndex, endElementIndex, startMetrics, blockProgression, direction, heightAndAdj);
					}
					else
					{
						blockRect = testILG.graphic.getBounds(textLine);
					}
					
					blockArray.push(blockRect);
				}
				
			}
			
			return blockArray;
		 }	
		 
		/** @private 
		 * 
		 * 
		 */
		 private function makeBlock(begElementIndex:int, endElementIndex:int, startMetrics:Rectangle, blockProgression:String, direction:String, heightAndAdj:Array):Rectangle
		 {
		 	var blockRect:Rectangle = new Rectangle();
			var globalStart:Point = new Point(0,0);
			var heightAndAdj:Array;
			
			if(begElementIndex > endElementIndex)
			{
				// swap the start and end
				var tempEndIdx:int = endElementIndex;
				endElementIndex = begElementIndex;
				begElementIndex = tempEndIdx;
			}
			var textLine:TextLine = getTextLine(true);
			
			//now that we have elements and they are in the right order for drawing, get their rectangles
			var begCharRect:Rectangle = textLine.getAtomBounds(begElementIndex);
			//trace(makeBlockPassCounter + ") begCharRect = " + begCharRect.toString());
			
			var endCharRect:Rectangle = textLine.getAtomBounds(endElementIndex);
			//trace(makeBlockPassCounter + ") endCharRect = " + endCharRect.toString());
			
			//Calculate the justificationRule value
			var justRule:String = _para.getEffectiveJustificationRule();
			//If this is TTB text and NOT TCY, as indicated by TextRotation.rotate0...
			if(blockProgression == BlockProgression.RL && textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
			{
				globalStart.y = begCharRect.y;
				blockRect.height = begElementIndex != endElementIndex ? endCharRect.bottom - begCharRect.top : begCharRect.height;
				
				//re-ordered this code.  EAST_ASIAN is more common in vertical and should be the first option.
				if(justRule == JustificationRule.EAST_ASIAN)
				{
					blockRect.width = begCharRect.width;
				}
				else
				{
					blockRect.width = heightAndAdj[0];
					globalStart.x -= heightAndAdj[1];
				}
			}
			else
			{
				//given bidi text alternations, the endCharRect could be left of the begCharRect,
				//use whichever is farther left.
				globalStart.x = (begCharRect.x < endCharRect.x ? begCharRect.x : endCharRect.x);
				//if we're here and the BlockProgression is TTB, then we're TCY.  Less frequent case, so make non-TCY
				//the first option...
				//NB - Never use baseline adjustments for TCY.  They don't make sense here.(I think) - gak 06.03.08
				if(blockProgression == BlockProgression.RL)
					globalStart.y = begCharRect.y + (startMetrics.width /2); // TODO-9/5/8:Behavior for leading down TBD
				
				
				if(justRule != JustificationRule.EAST_ASIAN)
				{
					blockRect.height = heightAndAdj[0];
					if(blockProgression == BlockProgression.RL)
						globalStart.x -= heightAndAdj[1];
					else 
						globalStart.y += heightAndAdj[1];
					//changed the width from a default of 2 to use the begCharRect.width so that point seletion
					//can choose to use the right or left side of the glyph when drawing a caret Watson 1876415/1876953- gak 08.19.09
					blockRect.width = begElementIndex != endElementIndex ? Math.abs(endCharRect.right - begCharRect.left) : begCharRect.width;
				}
				else
				{
					blockRect.height =  begCharRect.height;
						
					//changed the width from a default of 2 to use the begCharRect.width so that point seletion
					//can choose to use the right or left side of the glyph when drawing a caret Watson 1876415/1876953- gak 08.19.09
					blockRect.width = begElementIndex != endElementIndex ? Math.abs(endCharRect.right - begCharRect.left) : begCharRect.width;
				}
			}
			
			blockRect.x = globalStart.x;
			blockRect.y = globalStart.y;
			if(blockProgression == BlockProgression.RL)
			{
				if(textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
					blockRect.x -= textLine.descent;
				else //it's TCY
					blockRect.y -= (blockRect.height / 2)
			}
			else
			{
				blockRect.y += (textLine.descent - blockRect.height);
			}
			
			var tfl:TextFlowLine = textLine.userData as TextFlowLine;
			var curElem:FlowLeafElement = _para.findLeaf(textLine.textBlockBeginIndex + begElementIndex);
			var rotation:String = curElem.computedFormat.textRotation;
			
			//handle rotation.  For horizontal text, rotations of 90 or 180 cause the text
			//to draw under the baseline in a cosistent location.  Vertical text is a bit more complicated
			//in that a 90 rotation puts it immediately to the left of the Em Box, whereas 180 is one quarter
			//of the way in the Em Box. Fix for Watson 1915930 - gak 02.17.09
			if(rotation == TextRotation.ROTATE_180 || 
				rotation == TextRotation.ROTATE_90)
			{
				if(blockProgression != BlockProgression.RL)
					blockRect.y += (blockRect.height / 2);
				else
				{
					if(curElem.getParentByType(TCYElement) == null)
					{	
						if(rotation == TextRotation.ROTATE_90)
							blockRect.x -= blockRect.width;
						else
							blockRect.x -= (blockRect.width * .75);
					}
					else
					{
						if(rotation == TextRotation.ROTATE_90)
							blockRect.y += blockRect.height;
						else
							blockRect.y += (blockRect.height * .75);
					}
				}
			}
			
			
			return blockRect;
		 }
		 
		/** @private
		 * 
		 * 
		 */
		tlf_internal function convertLineRectToContainer(rect:Rectangle, constrainShape:Boolean):void
		{
			var textLine:TextLine = getTextLine();
			
			/* var globalStart:Point = new Point(rect.x, rect.y);

		 	//convert to controller coordinates...
			////trace(makeBlockPassCounter + ") globalStart = " + globalStart.toString());
			globalStart = textLine.localToGlobal(globalStart);
			////trace(makeBlockPassCounter + ") localToGlobal.globalStart = " + globalStart.toString());
			globalStart = container.globalToLocal(globalStart);
			////trace(makeBlockPassCounter + ") globalToLocal.globalStart = " + globalStart.toString());
			rect.x = globalStart.x;
			rect.y = globalStart.y; */
			
			// this is much simpler and actually more accurate - localToGlobal/globalToLocal does some rounding
			rect.x += textLine.x;
			rect.y += textLine.y;
			
			if (constrainShape)
			{
				var tf:TextFlow = _para.getTextFlow();
				var columnRect:Rectangle = controller.columnState.getColumnAt(this.columnIndex);
				constrainRectToColumn(tf,rect,columnRect,controller.horizontalScrollPosition,controller.verticalScrollPosition,controller.compositionWidth,controller.compositionHeight);
			}
		}
		
		/** @private */
		static tlf_internal function constrainRectToColumn(tf:TextFlow,rect:Rectangle,columnRect:Rectangle,hScrollPos:Number,vScrollPos:Number,compositionWidth:Number,compositionHeight:Number):void
		{		
			if(tf.computedFormat.lineBreak == LineBreak.EXPLICIT)
				return;
					
			var bp:String = tf.computedFormat.blockProgression;
			var direction:String = tf.computedFormat.direction;

			if(bp == BlockProgression.TB && !isNaN(compositionWidth))
			{	
				if(direction == Direction.LTR)
				{
					//make sure is doesn't go past the end of the container
					if(rect.left > (columnRect.x + columnRect.width + hScrollPos))
						rect.left = (columnRect.x + columnRect.width + hScrollPos);
					
					//make sure that if this is a selection and not a point selection, that 
					//we don't go beyond the end of the container...
					if(rect.right > (columnRect.x + columnRect.width + hScrollPos))
						rect.right = (columnRect.x + columnRect.width + hScrollPos);
				}
				else
				{
					if(rect.right < (columnRect.x + hScrollPos))
						rect.right = (columnRect.x + hScrollPos);
						
					if(rect.left < (columnRect.x + hScrollPos))
						rect.left = (columnRect.x + hScrollPos);
				}
			}
			else if (bp == BlockProgression.RL && !isNaN(compositionHeight))
			{
				if(direction == Direction.LTR)
				{
					//make sure is doesn't go past the end of the container
					if(rect.top > (columnRect.y + columnRect.height + vScrollPos))
						rect.top = (columnRect.y + columnRect.height + vScrollPos);
					
					//make sure that if this is a selection and not a point selection, that 
					//we don't go beyond the end of the container...
					if(rect.bottom > (columnRect.y + columnRect.height + vScrollPos))
						rect.bottom = (columnRect.y + columnRect.height + vScrollPos);
				}
				else
				{
					if(rect.bottom < (columnRect.y + vScrollPos))
						rect.bottom = (columnRect.y + vScrollPos);
						
					if(rect.top < (columnRect.y + vScrollPos))
						rect.top = (columnRect.y + vScrollPos);
				}
			}
		}
		 
		/** @private
		 * Helper method to hilight the portion of a block selection on this TextLine.  A selection display is created and added to the line's TextFrame with ContainerController addSelectionShape.
		 * @param begIdx absolute index of start of selection on this line.
		 * @param endIdx absolute index of end of selection on this line.
		 */
		tlf_internal function hiliteBlockSelection(selObj:Shape, selFormat:SelectionFormat, container:DisplayObject, begIdx:int,endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):void
		{
			// no container for overflow lines, or lines scrolled out 
			if (isDamaged() || !_controller)
				return;

			// CONFIG::debug { assert(_textLineCache != null, "bad call to hiliteBlockSelection"); }
	
			var textLine:TextLine = peekTextLine();
			if (!textLine || !textLine.parent)
				return;
								
			var paraStart:int = _para.getAbsoluteStart();
			begIdx -= paraStart;
			endIdx -= paraStart;
			
			createSelectionShapes(selObj, selFormat, container, begIdx, endIdx, prevLine, nextLine);
		} 
		
		/** @private
		 * Helper method to hilight a point selection on this TextLine.  x,y,w,h of the selection are calculated and ContainerController.drawPointSelection is called 
		 * @param idx absolute index of the point selection.
		 */
		tlf_internal function hilitePointSelection(selFormat:SelectionFormat, idx:int, container:DisplayObject, prevLine:TextFlowLine, nextLine:TextFlowLine):void
		{
			var rect:Rectangle = computePointSelectionRectangle(idx,container,prevLine,nextLine, true);
			if (rect)
				_controller.drawPointSelection(selFormat, rect.x, rect.y, rect.width, rect.height)
		}
		
		static private function setRectangleValues(rect:Rectangle,x:Number,y:Number,width:Number,height:Number):void
		{
			rect.x = x;
			rect.y = y;
			rect.width = width;
			rect.height = height;
		}
		/** @private */		
		tlf_internal function computePointSelectionRectangle(idx:int, container:DisplayObject, prevLine:TextFlowLine, nextLine:TextFlowLine, constrainSelRect:Boolean):Rectangle
		{
			if (isDamaged() || !_controller)
				return null;

			// CONFIG::debug { assert(_textLineCache != null, "bad call to hiliteBlockSelection"); }
	
			// no container for overflow lines, or lines scrolled out 
			var textLine:TextLine = peekTextLine();
			if (!textLine || !textLine.parent)
				return null;			
			// adjust to this paragraph's TextBlock
			idx -= _para.getAbsoluteStart();

			textLine = getTextLine(true);
			
			//endIdx will only differ if idx is altered when detecting TCY bounds
			var endIdx:int = idx;
			var elementIndex:int = textLine.getAtomIndexAtCharIndex(idx);
			CONFIG::debug{ assert(elementIndex != -1, "Invalid point selection index! idx = " + idx); }
			
			var isTCYBounds:Boolean = false;
			var paraLeadingTCY:Boolean = false;
			
			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
			CONFIG::debug { assert(contElement != null,"para with no container"); }
			var blockProgression:String = contElement.computedFormat.blockProgression;
			var direction:String = _para.computedFormat.direction;
			
			//need to check for TCY.  TCY cannot take input into it's head, but can in it's tail.
			if(blockProgression == BlockProgression.RL)
			{
				if (idx == 0)
				{ 
					if(textLine.getAtomTextRotation(0) == TextRotation.ROTATE_0)
						paraLeadingTCY = true;
				}
				else
				{
					var prevElementIndex:int = textLine.getAtomIndexAtCharIndex(idx - 1);
					if(prevElementIndex != -1)
					{
						//if this elem is TCY, then we need to back up one space and use the right bounds
						if(textLine.getAtomTextRotation(elementIndex) == TextRotation.ROTATE_0 && 
							textLine.getAtomTextRotation(prevElementIndex) != TextRotation.ROTATE_0)
						{
							elementIndex = prevElementIndex;
							--idx;
							isTCYBounds = true;
						}
						else if(textLine.getAtomTextRotation(prevElementIndex) == TextRotation.ROTATE_0)
						{
							elementIndex = prevElementIndex;
							--idx;
							isTCYBounds = true;
						}
					}
				}
			}
			
			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
			var blockRectArray:Array = makeSelectionBlocks(idx, endIdx, _para.getAbsoluteStart(), blockProgression, direction, heightAndAdj);
			CONFIG::debug{ assert(blockRectArray.length == 1, "A point selection should return a single selection rectangle!"); }
			var rect:Rectangle = blockRectArray[0];
			
			convertLineRectToContainer(rect, constrainSelRect);
			
			var drawOnRight:Boolean = (direction == Direction.RTL);
				
			if((drawOnRight && textLine.getAtomBidiLevel(elementIndex) % 2 == 0) || 
				(!drawOnRight && textLine.getAtomBidiLevel(elementIndex) % 2 != 0))
			{
				drawOnRight = !drawOnRight;
			}
			
			if(blockProgression == BlockProgression.RL && textLine.getAtomTextRotation(elementIndex) != TextRotation.ROTATE_0)
			{
				if(!drawOnRight)
					setRectangleValues(rect, rect.x, !isTCYBounds ? rect.y : rect.y + rect.height,rect.width,1);
				else
					setRectangleValues(rect, rect.x, !isTCYBounds ? rect.y + rect.height : rect.y ,rect.width,1);
			}
			else
			{
				//choose to use the right or left side of the glyph based on Direction when drawing a caret Watson 1876415/1876953
				//if the direction is ltr, then the cursor should be on the left side
				if(!drawOnRight)
					setRectangleValues(rect, !isTCYBounds ? rect.x : rect.x + rect.width, rect.y, 1, rect.height);
				else //otherwise, it should be on the right, unless it is TCY
					setRectangleValues(rect, !isTCYBounds ? rect.x + rect.width : rect.x, rect.y, 1, rect.height);
			}
				
			//allow the atoms to be garbage collected.
			textLine.flushAtomData();
			
			return rect;
  		}
  		
  		/** @private
  		 * Three states.  Disjoint(0), Intersects(1), HeightContainedIn(2),  
  		 */
  		 
  		tlf_internal function selectionWillIntersectScrollRect(scrollRect:Rectangle, begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):int
  		{
  			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
			CONFIG::debug { assert(contElement != null,"para with no container"); }
			var blockProgression:String = contElement.computedFormat.blockProgression;
			var textLine:TextLine = getTextLine(true);
			
  			if (begIdx == endIdx)
  			{
  				var pointSelRect:Rectangle = computePointSelectionRectangle(begIdx, DisplayObject(controller.container), prevLine, nextLine, false);
  				if (pointSelRect)
  				{
  					if (scrollRect.containsRect(pointSelRect))
  						return 2;
	  				if (scrollRect.intersects(pointSelRect))
	  					return 1;
	  			}
  			}
  			else
  			{
				var paraStart:int = _para.getAbsoluteStart();
  				var selCache:SelectionCache = this.getSelectionShapesCacheEntry(begIdx-paraStart,endIdx-paraStart,prevLine,nextLine,blockProgression);
  				if (selCache)
  				{
  					//iterate the blocks and check for intersections
					var drawRect:Rectangle;
					for each (drawRect in selCache.selectionBlocks)
					{
						drawRect = drawRect.clone();
						// convertLineRectToContainer(container, drawRect);
						drawRect.x += textLine.x; 
						drawRect.y += textLine.y; 
						if (scrollRect.intersects(drawRect))
						{
							if(blockProgression == BlockProgression.RL)
							{
								// see if width is entirely contained in scrollRect
								if (drawRect.left >= scrollRect.left && drawRect.right <= scrollRect.right)
									return 2;
							}
							else
							{
								if (drawRect.top >= scrollRect.top && drawRect.bottom <= scrollRect.bottom)
									return 2;
							}
							return 1;
						}
					}
  				}
  			}
  			return 0;
  		}
  		

		/** @private */
		CONFIG::debug private static function dumpAttribute(result:String, attributeName:String, attributeValue:Object):String
		{
			if (attributeValue)
			{
				result += " ";
				result += attributeName;
				result += "=\"";
				result += attributeValue.toString();
				result += "\""	
			}
			return result;		
		}
		
		/** @private
		 */
		private function normalizeRects(srcRects:Array, dstRects:Array, largestRise:Number, blockProgression:String, direction:String):void
		{
			//the last rectangle in the list with a potential to merge
			var lastRect:Rectangle = null;
			var rectIter:int = 0;
			while(rectIter < srcRects.length)
			{
				//get the current rect and advance the iterator
				var rect:Rectangle = srcRects[rectIter++];
				
				//apply a new height if needed.
				if(blockProgression == BlockProgression.RL)
				{
					if(rect.width < largestRise)
					{
						rect.width = largestRise;
					}
				}
				else
				{
					if(rect.height < largestRise)
					{
						rect.height = largestRise;
					}
				}
				//if the lastRect is null, no need to perform calculation
				if(lastRect == null)
				{
					lastRect = rect;
				}
				else
				{
					//TCY has already been excluded, so no need to worry about it here...
					if(blockProgression == BlockProgression.RL)
					{
						//trace(normalCounter + ") lastRect = " + lastRect.toString());
						//trace(normalCounter + ") rect = " + rect.toString());
						
						//merge it in to the last rect
						if(lastRect.y < rect.y && (lastRect.y + lastRect.height) >= rect.top && lastRect.x == rect.x)
						{
							lastRect.height += rect.height;
						}
						else if(rect.y < lastRect.y && lastRect.y <= rect.bottom && lastRect.x == rect.x)
						{
							lastRect.height += rect.height;
							lastRect.y = rect.y;
						}
						else
						{
							//we have a break in the rectangles and should push last rect onto the draw list before continuing
							dstRects.push(lastRect);
							lastRect = rect;
						}
					}
					else
					{
						if(lastRect.x < rect.x && (lastRect.x + lastRect.width) >= rect.left && lastRect.y == rect.y)
						{
							lastRect.width += rect.width;
						}
						else if(rect.x < lastRect.x && lastRect.x <= rect.right && lastRect.y == rect.y)
						{
							lastRect.width += rect.width;
							lastRect.x = rect.x;
						}
						else
						{
							//we have a break in the rectangles and should push last rect onto the draw list before continuing
							dstRects.push(lastRect);
							lastRect = rect;
						}
					}
				}
				//if this is the last rectangle, we haven't added it, do so now.
				if(rectIter == srcRects.length)
					dstRects.push(lastRect);
			}
		}
		
		/** @private */
		private function adjustEndElementForBidi(begIdx:int, endIdx:int, begElementIndex:int, direction:String):int
		{
			var endElementIndex:int = begElementIndex;
			
			var textLine:TextLine = getTextLine(true);
			
			if(endIdx != begIdx)
			{
				if(((direction == Direction.LTR && textLine.getAtomBidiLevel(begElementIndex)%2 != 0)
					|| (direction == Direction.RTL && textLine.getAtomBidiLevel(begElementIndex)%2 == 0))
					&& textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
					endElementIndex = textLine.getAtomIndexAtCharIndex(endIdx);
				else
				{
					endElementIndex = textLine.getAtomIndexAtCharIndex(endIdx - 1);
				}
			}
			
			if(endElementIndex == -1 && endIdx > 0)
			{
				return adjustEndElementForBidi(begIdx, endIdx - 1, begElementIndex, direction);
			}
			return endElementIndex;
		}
		
		/** @private */
		private function isAtomBidi(elementIdx:int, direction:String):Boolean
		{
			var textLine:TextLine = getTextLine(true);
			
			return (textLine.getAtomBidiLevel(elementIdx)%2 != 0 && direction == Direction.LTR) || (textLine.getAtomBidiLevel(elementIdx)%2 == 0 && direction == Direction.RTL);
		}
		
		/** @private */
		tlf_internal function get adornCount():int 
		{ return _adornCount; }
		
		/** @private */
		CONFIG::debug public function dumpToXML():String
		{
			var result:String = new String("<line");
		
			result = dumpAttribute(result, "absoluteStart", absoluteStart);
			result = dumpAttribute(result, "textLength", textLength);
			result = dumpAttribute(result, "height", height);
			result = dumpAttribute(result, "spaceBefore", spaceBefore);

			result = dumpAttribute(result, "spaceAfter", spaceAfter);
			result = dumpAttribute(result, "location", location);
			result = dumpAttribute(result, "x", x);
			result = dumpAttribute(result, "y", y);
			result = dumpAttribute(result, "targetWidth", targetWidth);
			result = dumpAttribute(result, "lineOffset", _lineOffset);
			result += ">\n";
			
			
			var textLine:TextLine = getTextLine(true);
			
			result += "<TextBlock>";
			result += textLine.textBlock.dump(); 
			result += "</TextBlock>";
			result += "<TextLine>"
			result += textLine.dump();
			result += "</TextLine>"
			
			result += "</line>";
			return result;
		}
		
	};
}

import flash.geom.Rectangle;

import flashx.textLayout.edit.ISelectionManager;

/** @private - I would have defined this as tlf_internal, but that is not an option, so
 * making it private.
 * 
 * The SelectionCache is a structure designed to hold a few key data points needed to quickly
 * reconstruct a selection on a line:
 * 
 * a) the beginning and end indicies of the selection on the line
 * b) the regular selection rectangles
 * c) the irregular selection rectangles, such as TCY selection rects in vertical text
 * 
 **/
final class SelectionCache
{
	private var _begIdx:int = -1;
	private var _endIdx:int = -1;
	
	private var _selectionBlocks:Array = null;
	
	public function SelectionCache()
	{
	}
	
	public function get begIdx():int 
	{ return _begIdx; }
	public function set begIdx(val:int):void	
	{ _begIdx = val; }
	
	public function get endIdx():int 
	{ return _endIdx; }
	public function set endIdx(val:int):void	
	{ _endIdx = val; }
	
	public function pushSelectionBlock(drawRect:Rectangle):void 
	{
		if(!_selectionBlocks)
			_selectionBlocks = new Array();
			
		_selectionBlocks.push(drawRect.clone());
	}
	
	public function get selectionBlocks():Array 
	{ return _selectionBlocks; }
	
	
	public function clear():void
	{
		_selectionBlocks = null;
		_begIdx = -1;
		_endIdx = -1;
	}
	
}
