flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ha...@apache.org
Subject [35/42] flex-asjs git commit: And here’s TLF…
Date Thu, 16 Mar 2017 13:37:55 GMT
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowLineLocation.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowLineLocation.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowLineLocation.as
new file mode 100644
index 0000000..e6483dc
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowLineLocation.as
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose
+{	
+	/** 
+	 * The TextFlowLineLocation class is an enumeration class that defines constants for specifying the location
+	 * of a line within a paragraph.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see ParagraphElement
+	 * @see TextFlow
+	 */
+	 
+	public final class TextFlowLineLocation
+	{ 
+		/** Specifies the first line in a paragraph. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const FIRST:uint = 1;
+		
+		/** Specifies a middle line in a paragraph - neither the first nor the last line. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const MIDDLE:uint = 2;
+		
+		/** Specifies the last line in a paragraph.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public static const LAST:uint = 4;
+		
+		/** Specifies both the first and last lines in a paragraph.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const ONLY:uint = 5;
+	};
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowTableBlock.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowTableBlock.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowTableBlock.as
new file mode 100644
index 0000000..a1189c2
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextFlowTableBlock.as
@@ -0,0 +1,266 @@
+// //////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.compose
+{
+	import org.apache.flex.textLayout.container.IContainerController;
+	import org.apache.flex.core.IParentIUIBase;
+	import org.apache.flex.graphics.ICompoundGraphic;
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.textLayout.edit.SelectionFormat;
+	import org.apache.flex.textLayout.elements.CellContainer;
+	import org.apache.flex.textLayout.elements.CellCoordinates;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.ITableCellElement;
+	import org.apache.flex.textLayout.elements.ITableElement;
+	import org.apache.flex.textLayout.elements.TableBlockContainer;
+
+	/**
+	 * 
+	 **/
+	public class TextFlowTableBlock extends TextFlowLine implements ITextFlowTableBlock
+	{
+		private var _textHeight:Number;
+
+		/** Constructor - creates a new TextFlowTableBlock instance. 
+		 *  <p><strong>Note</strong>: No client should call this. It's exposed for writing your own composer.</p>
+		 *
+		 * @param index The index in the Table text flow.
+		 * */
+		public function TextFlowTableBlock(index:uint)
+		{
+			blockIndex = index;
+			_container = new TableBlockContainer();
+			super(null, null);
+		}
+
+		override public function get composable():Boolean
+		{
+			return false;
+		}
+
+		/**
+		 * @inheritDoc
+		 **/
+		override public function initialize(paragraph:IParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0, textLine:ITextLine = null):void
+		{
+			_container.userData = this;
+			_lineOffset = lineOffset;
+
+			super.initialize(paragraph, outerTargetWidth, lineOffset, absoluteStart, numChars, textLine);
+		}
+
+		override public function setController(cont:IContainerController, colNumber:int):void
+		{
+			super.setController(cont, colNumber);
+			if (cont)
+				controller.addComposedTableBlock(container);
+		}
+
+		/**
+		 * The table that owns this table block
+		 **/
+		private var _parentTable:ITableElement;
+		/**
+		 * The index of this block in the table text flow layout
+		 **/
+		public var blockIndex:uint = 0;
+		/**
+		 * @private
+		 **/
+		private var _container:TableBlockContainer;
+		private var _cells:Array;
+
+		/**
+		 * Returns an array of table cells. 
+		 * @private
+		 **/
+		private function getCells():Array
+		{
+			if (_cells == null)
+			{
+				_cells = [];
+			}
+			return _cells;
+		}
+
+		/**
+		 * Returns a vector of table cell elements in the given cell range. 
+		 **/
+		public function getCellsInRange(anchorCoords:CellCoordinates, activeCoords:CellCoordinates):Vector.<ITableCellElement>
+		{
+			if (!parentTable)
+				return null;
+			return parentTable.getCellsInRange(anchorCoords, activeCoords, this);
+		}
+
+		/**
+		 * Clears the cells in the table block. Wraps clearCells(). 
+		 **/
+		public function clear():void
+		{
+			clearCells();
+		}
+
+		/**
+		 * Clears the cells in the table block
+		 **/
+		public function clearCells():void
+		{
+			while (_container.numElements)
+			{
+				_container.removeElement(_container.getElementAt(0));
+			}
+			getCells().length = 0;
+		}
+
+		/**
+		 * Adds a cell container to table container. This adds it to the display list. 
+		 * If the cell is already added it does not add it twice. 
+		 **/
+		public function addCell(cell:CellContainer):void
+		{
+			var cells:Array = getCells();
+			if (cells.indexOf(cell) < 0)
+			{
+				cells.push(cell);
+				_container.addElement(cell);
+			}
+		}
+
+		public function drawBackground(backgroundInfo:*):void
+		{
+			// TODO: need to figure this out...
+		}
+
+		/**
+		 * Container that displays this collection of cells
+		 **/
+		public function get container():TableBlockContainer
+		{
+			return _container;
+		}
+
+		/**
+		 * Triggers drawing of composed cell contents
+		 **/
+		public function updateCompositionShapes():void
+		{
+			var cells:Array = getCells();
+			for each (var cell:CellContainer in cells)
+			{
+				cell.cellElement.updateCompositionShapes();
+			}
+		}
+
+		/**
+		 * Sets the height of the container 
+		 **/
+		override public function set height(value:Number):void
+		{
+			// _container.height = value;
+			_textHeight = value;
+		}
+
+		/**
+		 * @inheritDoc
+		 **/
+		override public function get height():Number
+		{
+			return _textHeight;
+		}
+
+		/**
+		 * Sets the width of the container 
+		 **/
+		public function set width(value:Number):void
+		{
+			_container.width = value;
+		}
+
+		/**
+		 * Gets the width of the container 
+		 **/
+		public function get width():Number
+		{
+			return _container.width;
+		}
+
+		/**
+		 * Sets the x position of the container
+		 **/
+		override public function set x(value:Number):void
+		{
+			super.x = _container.x = value;
+		}
+
+		override public function get x():Number
+		{
+			return _container.x;
+		}
+
+		/**
+		 * Sets the y value of the container
+		 **/
+		override public function set y(value:Number):void
+		{
+			super.y = _container.y = value;
+		}
+
+		override public function get y():Number
+		{
+			return _container.y;
+		}
+
+		/**
+		 * Returns a vector of table cell elements.
+		 **/
+		public function getTableCells():Vector.<ITableCellElement>
+		{
+			var tCells:Vector.<ITableCellElement> = new Vector.<ITableCellElement>();
+			var cells:Array = getCells();
+
+			for each (var cellContainer:CellContainer in cells)
+			{
+				tCells.push(cellContainer.cellElement);
+			}
+
+			return tCells;
+		}
+
+		public override function get textHeight():Number
+		{
+			return _textHeight;
+		}
+
+		public override function hiliteBlockSelection(selObj:ICompoundGraphic, selFormat:SelectionFormat, container:IParentIUIBase, begIdx:int, endIdx:int, prevLine:ITextFlowLine, nextLine:ITextFlowLine):void
+		{
+			// do nothing for now...
+		}
+
+		public function get parentTable():ITableElement
+		{
+			return _parentTable;
+		}
+
+		public function set parentTable(parentTable:ITableElement):void
+		{
+			this._parentTable = parentTable;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextLineRecycler.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextLineRecycler.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextLineRecycler.as
new file mode 100644
index 0000000..e2ae145
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/TextLineRecycler.as
@@ -0,0 +1,129 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose
+{	
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.utils.ObjectMap;
+	
+	CONFIG::debug { import org.apache.flex.textLayout.debug.assert; }
+
+	
+
+	
+	
+	/** 
+	 * The TextLineRecycler class provides support for recycling of TextLines.  Some player versions support a recreateTextLine.  Passing TextLines
+	 * to the recycler makes them available for reuse.  This improves Player performance.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */ 
+	public class TextLineRecycler
+	{
+		static private const _textLineRecyclerCanBeEnabled:Boolean = true;
+		static private var _textLineRecyclerEnabled:Boolean = _textLineRecyclerCanBeEnabled;
+		
+		/** Controls if the TLF recycler enabled.   It can only be enabled in 10.1 or later players.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function get textLineRecyclerEnabled():Boolean
+		{ return _textLineRecyclerEnabled; }
+		static public function set textLineRecyclerEnabled(value:Boolean):void
+		{ _textLineRecyclerEnabled = value ? _textLineRecyclerCanBeEnabled : false; }
+		
+		// manage a cache of ITextLine's that can be reused
+		// This version uses a dictionary that holds the TextLines as weak references
+		static private var reusableLineCache:ObjectMap = new ObjectMap(true);
+		
+		/**
+		 * Add a ITextLine to the pool for reuse. TextLines for reuse should have null userData and null parent. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		static public function addLineForReuse(textLine:ITextLine):void
+		{
+			CONFIG::debug { assert(textLine.parent == null && textLine.userData == null && (textLine.validity == "invalid" || textLine.validity == "static"),"textLine not ready for reuse"); }
+			if (_textLineRecyclerEnabled)
+			{
+				CONFIG::debug 
+				{
+					for each (var line:ITextLine in reusableLineCache)
+					{
+						 assert(line != textLine,"READDING LINE TO CACHE");
+					}
+				}
+				CONFIG::debug { cacheTotal++; }
+				reusableLineCache[textLine] = null;
+			}
+		} 
+		CONFIG::debug
+		{
+			/** @private */
+			static public var cacheTotal:int = 0;
+			/** @private */
+			static public var fetchTotal:int = 0;
+			/** @private */
+			static public var hitTotal:int = 0;		
+			
+			static private function recordFetch(hit:int):void
+			{
+				fetchTotal++;
+				hitTotal += hit;
+				
+				/*if ((fetchTotal%100) == 0)
+					trace(fetchTotal,hitTotal,cacheTotal);*/
+			}
+		}
+		
+		/**
+		 * Return a ITextLine from the pool for reuse. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		static public function getLineForReuse():ITextLine
+		{
+			if (_textLineRecyclerEnabled)
+			{
+				for (var obj:Object in reusableLineCache)
+				{
+					// remove from the cache
+					delete reusableLineCache[obj];
+					CONFIG::debug { assert(reusableLineCache[obj] === undefined,"Bad delete"); }
+					CONFIG::debug { recordFetch(1); }
+					return obj as ITextLine;
+				}
+				CONFIG::debug { recordFetch(0); }
+			}
+			return null;
+		}
+		
+		/** @private empty the reusableLineCache */
+		static public function emptyReusableLineCache():void
+		{
+			reusableLineCache = new ObjectMap(true);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/VerticalJustifier.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/VerticalJustifier.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/VerticalJustifier.as
new file mode 100644
index 0000000..0adee48
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/VerticalJustifier.as
@@ -0,0 +1,351 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose
+{
+	import org.apache.flex.textLayout.container.IContainerController;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.formats.BlockProgression;
+	import org.apache.flex.textLayout.formats.Float;
+	import org.apache.flex.textLayout.formats.VerticalAlign;
+
+	
+
+	
+	/** @private
+	 * Adjust line positions according to verticalAlign settings.  Vertical alignment is perpendicular
+	 * to the linebreak direction.
+	 */
+	public final class VerticalJustifier
+	{
+		[ ArrayElementType("org.apache.flex.textLayout.compose.IVerticalJustificationLine") ] 
+		/** Vertical justify the subset of lines from startIndext to startIndex to numLines according to the rule specified by verticalAlignAttr.  
+		 * The assumption is that they are all the lines in a single column of cont. 
+		 * @see text.formats.VerticalAlign
+		 * @return adjustment applied to the first line in the column.
+		 * */
+		static public function applyVerticalAlignmentToColumn(controller:IContainerController, verticalAlignAttr:String, lines:Array, startIndex:int, numLines:int,beginFloatIndex:int,endFloatIndex:int):Number
+		{
+			var helper:IVerticalAdjustmentHelper;
+			if (controller.rootElement.computedFormat.blockProgression == BlockProgression.RL)
+				helper = new RL_VJHelper(controller);
+			else
+				helper = new TB_VJHelper(controller);
+				
+			CONFIG::debug { assert(startIndex + numLines <= lines.length && numLines > 0,"applyVerticalAlignmentToColumn: bad indices"); }
+									
+			var i:int;
+			var rslt:Number;
+			
+			switch(verticalAlignAttr) 
+			{
+				case VerticalAlign.MIDDLE:
+				case VerticalAlign.BOTTOM:
+					var lastLine:IVerticalJustificationLine = lines[(startIndex + numLines) - 1];
+					var bottom:Number = helper.getBottom(lastLine, controller, beginFloatIndex, endFloatIndex);
+					rslt = (verticalAlignAttr == VerticalAlign.MIDDLE) ? helper.computeMiddleAdjustment(bottom) : helper.computeBottomAdjustment(bottom);
+					for (i = startIndex; i < startIndex + numLines; i++)	// Adjust line positions
+						helper.applyAdjustment(lines[i]);
+					for (var floatIndex:int = beginFloatIndex; floatIndex < endFloatIndex; floatIndex++)	// Adjust float positions
+					{
+						var floatInfo:FloatCompositionData = controller.getFloatAt(floatIndex);
+						if (floatInfo.floatType != Float.NONE)
+							helper.applyAdjustmentToFloat(floatInfo);	
+					}
+					break;
+				case VerticalAlign.JUSTIFY:
+					rslt = helper.computeJustifyAdjustment(lines, startIndex, numLines);
+					helper.applyJustifyAdjustment(lines, startIndex, numLines);
+					break;
+			}
+
+			//for (i = startIndex; i < startIndex + numLines; i++)
+			//	trace("x=", sc[i].x, "y=", sc[i].y, "yAdj=", yAdj);
+			return rslt;
+		}
+	}
+}
+
+import org.apache.flex.textLayout.compose.FloatCompositionData;
+import org.apache.flex.textLayout.compose.IVerticalJustificationLine;
+import org.apache.flex.textLayout.compose.ITextFlowLine;
+import org.apache.flex.textLayout.container.IContainerController;
+import org.apache.flex.textLayout.elements.IInlineGraphicElement;
+import org.apache.flex.textLayout.formats.Float;
+
+interface IVerticalAdjustmentHelper
+{
+	function getBottom(line:IVerticalJustificationLine, controller:IContainerController, beginFloat:int, endFloat:int):Number;
+	
+	function computeMiddleAdjustment(bottom:Number):Number;
+	function applyAdjustment(line:IVerticalJustificationLine):void;
+	function applyAdjustmentToFloat(floatInfo:FloatCompositionData):void;
+	
+	function computeBottomAdjustment(bottom:Number):Number;
+	
+	function computeJustifyAdjustment(lineArray:Array, firstLine:int, numLines:int):Number;
+	function applyJustifyAdjustment(lineArray:Array, firstLine:int, numLines:int):void;
+}
+
+class TB_VJHelper implements IVerticalAdjustmentHelper
+{
+	
+
+	
+	private var _textFrame:IContainerController;
+	private var adj:Number;
+	
+	public function TB_VJHelper(tf:IContainerController):void
+	{
+		_textFrame = tf;
+	}
+	
+	public function getBottom(line:IVerticalJustificationLine, controller:IContainerController, beginFloat:int, endFloat:int):Number
+	{
+		var maxBottom:Number = getBaseline(line) + line.descent;
+		for (var i:int = beginFloat; i < endFloat; ++i)
+		{
+			var floatInfo:FloatCompositionData = controller.getFloatAt(i);
+			if (floatInfo.floatType != Float.NONE)
+			{
+				var ilg:IInlineGraphicElement = controller.rootElement.findLeaf(floatInfo.absolutePosition) as IInlineGraphicElement;
+				maxBottom = Math.max(maxBottom, floatInfo.y + ilg.elementHeightWithMarginsAndPadding());
+			}
+		}
+		return maxBottom;
+	}
+	
+	public function getBottomOfLine(line:IVerticalJustificationLine):Number
+	{
+		return getBaseline(line) + line.descent;
+	}
+	
+	private function getBaseline(line:IVerticalJustificationLine):Number
+	{
+		if (line is ITextFlowLine)
+			return line.y + line.ascent;
+		else
+			return line.y;
+	}
+	
+	private function setBaseline(line:IVerticalJustificationLine, pos:Number):void
+	{
+		if (line is ITextFlowLine)
+			line.y = pos - line.ascent;
+		else
+			line.y = pos;
+	}
+	
+	// half of the available adjustment added to each y to shift the lines half way down the frame
+	public function computeMiddleAdjustment(contentBottom:Number):Number
+	{
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.getTotalPaddingBottom());
+		adj = (frameBottom - contentBottom) / 2;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+		return adj;
+	}
+	// the baseline of the last line should be at the bottom of the frame - paddingBottom.
+	public function computeBottomAdjustment(contentBottom:Number):Number
+	{
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.getTotalPaddingBottom());
+		adj = frameBottom - contentBottom;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+		return adj;
+	}
+
+	public function applyAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.y = line.y + adj;
+	}
+	
+	public function applyAdjustmentToFloat(floatInfo:FloatCompositionData):void
+	{
+		floatInfo.y += adj;
+	}
+	
+	// one line: untouched, two lines: first line untouched and descent of last line at the bottom of the frame, 
+	// and more than two lines: line spacing increased proportionally, with first line untouched and descent of last line at the bottom of the frame
+	[ ArrayElementType("org.apache.flex.textLayout.compose.IVerticalJustificationLine") ]
+	public function computeJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):Number
+	{
+		adj = 0;
+		
+		if (numLines == 1)
+		{
+			return 0;	// do nothing
+		}
+		
+		// first line unchanged	
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var firstBaseLine:Number =  getBaseline(firstLine);
+
+		// descent of the last line on the bottom of the frame	
+		var lastLine:IVerticalJustificationLine = lineArray[firstLineIndex + numLines - 1];
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.getTotalPaddingBottom());
+		var allowance:Number = frameBottom - getBottomOfLine(lastLine);
+		if (allowance < 0)
+		{
+			return 0; // Some text scrolled out; don't justify
+		}
+		var lastBaseLine:Number = getBaseline(lastLine); 
+	
+		adj = allowance/(lastBaseLine - firstBaseLine); // multiplicative factor by which the space between consecutive lines is increased 
+		return adj;
+	}
+	
+	[ ArrayElementType("org.apache.flex.textLayout.compose.IVerticalJustificationLine") ]
+	public function applyJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{ 
+		if (numLines == 1 || adj == 0)
+			return;	// do nothing
+			
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var prevBaseLine:Number = getBaseline(firstLine);
+		var prevBaseLineUnjustified:Number = prevBaseLine;
+		
+		var line:IVerticalJustificationLine;
+		var currBaseLine:Number;
+		var currBaseLineUnjustified:Number;
+		
+		for (var i:int = 1; i < numLines; i++)
+		{
+			line = lineArray[i + firstLineIndex];
+			currBaseLineUnjustified = getBaseline(line);
+			
+			// Space between consecutive baselines scaled up by the calculated factor
+			currBaseLine = prevBaseLine  + (currBaseLineUnjustified - prevBaseLineUnjustified)*(1 + adj);
+			setBaseline(line, currBaseLine);
+			
+			prevBaseLineUnjustified = currBaseLineUnjustified;
+			prevBaseLine = currBaseLine;
+		}
+	}
+}
+
+class RL_VJHelper implements IVerticalAdjustmentHelper
+{
+	
+
+
+	private var _textFrame:IContainerController;
+	private var adj:Number = 0;
+	
+	public function RL_VJHelper(tf:IContainerController):void
+	{
+		_textFrame = tf;
+	}
+	
+	public function getBottom(lastLine:IVerticalJustificationLine, controller:IContainerController, beginFloat:int, endFloat:int):Number
+	{
+		var frameWidth:Number = _textFrame.compositionWidth - Number(_textFrame.getTotalPaddingLeft());
+		var maxLeft:Number = (frameWidth + lastLine.x - lastLine.descent);
+		for (var i:int = beginFloat; i < endFloat; ++i)
+		{
+			var floatInfo:FloatCompositionData = controller.getFloatAt(i);
+			if (floatInfo.floatType != Float.NONE)
+				maxLeft = Math.min(maxLeft, floatInfo.x + frameWidth);
+		}
+		return maxLeft;
+	}
+	
+	// half of the available adjustment added to each x to shift the lines half way left across the frame
+	public function computeMiddleAdjustment(contentLeft:Number):Number
+	{
+		adj = contentLeft / 2;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+		return -adj;
+	}
+	// the baseline of the last line should be at the bottom of the frame - paddingLeft.
+	public function computeBottomAdjustment(contentLeft:Number):Number
+	{
+		adj = contentLeft;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+		return -adj;
+	}
+	
+	public function applyAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.x = (line.x - adj);
+	}
+	
+	public function applyAdjustmentToFloat(floatInfo:FloatCompositionData):void
+	{
+		floatInfo.x -= adj;
+	}
+	
+	// one line: untouched, two lines: first line untouched and descent of last line at the bottom of the frame, 
+	// and more than two lines: line spacing increased proportionally, with first line untouched and descent of last line at the bottom of the frame
+	[ ArrayElementType("org.apache.flex.textLayout.compose.IVerticalJustificationLine") ]
+	public function computeJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):Number
+	{ 
+		adj = 0;
+		
+		if (numLines == 1)
+			return 0;	// do nothing
+			
+		// first line unchanged
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var firstBaseLine:Number =  firstLine.x;
+		
+		// descent of the last line on the left of the frame	
+		var lastLine:IVerticalJustificationLine = lineArray[firstLineIndex + numLines - 1];
+		var frameLeft:Number =  Number(_textFrame.getTotalPaddingLeft()) - _textFrame.compositionWidth;
+		var allowance:Number = (lastLine.x - lastLine.descent) - frameLeft;
+		if (allowance < 0)
+		{
+			return 0; // Some text scrolled out; don't justify
+		}
+		var lastBaseLine:Number = lastLine.x;  
+		
+		adj = allowance/(firstBaseLine - lastBaseLine);  // multiplicative factor by which the space between consecutive lines is increased 
+		return -adj;
+	}
+	
+	[ ArrayElementType("org.apache.flex.textLayout.compose.IVerticalJustificationLine") ]
+	public function applyJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{
+		if (numLines == 1 || adj == 0)
+			return;	// do nothing
+			
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var prevBaseLine:Number = firstLine.x;
+		var prevBaseLineUnjustified:Number = prevBaseLine;
+		
+		var line:IVerticalJustificationLine;
+		var currBaseLine:Number;
+		var currBaseLineUnjustified:Number;
+		
+		for (var i:int = 1; i < numLines; i++)
+		{
+			line = lineArray[i + firstLineIndex];
+			currBaseLineUnjustified = line.x;
+			
+			// Space between consecutive baselines scaled up by the calculated factor
+			currBaseLine = prevBaseLine - (prevBaseLineUnjustified - currBaseLineUnjustified)*(1 + adj);
+			line.x = currBaseLine;
+			
+			prevBaseLineUnjustified = currBaseLineUnjustified;
+			prevBaseLine = currBaseLine;
+		}		
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/AdornmentUtils.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/AdornmentUtils.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/AdornmentUtils.as
new file mode 100644
index 0000000..477e386
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/AdornmentUtils.as
@@ -0,0 +1,685 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.elements.utils.GeometricElementUtils;
+	import org.apache.flex.core.IUIBase;
+	import org.apache.flex.textLayout.dummy.BoundsUtil;
+	import org.apache.flex.textLayout.elements.IFlowElement;
+	import org.apache.flex.textLayout.elements.ISubParagraphGroupElementBase;
+	import org.apache.flex.textLayout.formats.Float;
+	import org.apache.flex.graphics.SolidColor;
+	import org.apache.flex.textLayout.elements.ITCYElement;
+	import org.apache.flex.text.engine.TextBaseline;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+	import org.apache.flex.graphics.SolidColorStroke;
+	import org.apache.flex.textLayout.formats.JustificationRule;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.graphics.PathBuilder;
+	import org.apache.flex.graphics.ICompoundGraphic;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.formats.BackgroundColor;
+	import org.apache.flex.textLayout.formats.TextDecoration;
+	import org.apache.flex.text.engine.TextRotation;
+	import org.apache.flex.textLayout.compose.ITextFlowLine;
+	import org.apache.flex.textLayout.formats.BlockProgression;
+	import org.apache.flex.core.IParentIUIBase;
+	import org.apache.flex.textLayout.elements.InlineGraphicElementStatus;
+	import org.apache.flex.textLayout.elements.IInlineGraphicElement;
+	import org.apache.flex.textLayout.formats.TextLayoutFormat;
+	import org.apache.flex.textLayout.formats.BaselineShift;
+	import org.apache.flex.geom.Rectangle;
+	import org.apache.flex.textLayout.formats.IMEStatus;
+	import org.apache.flex.text.engine.FontMetrics;
+	import org.apache.flex.textLayout.utils.CharacterUtil;
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+
+	public class AdornmentUtils
+	{
+				/** @private */
+		public static function getSpanBoundsOnLine(element:IFlowLeafElement,textLine:ITextLine, blockProgression:String):Array
+		{
+			var line:ITextFlowLine = ITextFlowLine(textLine.userData);
+			var paraStart:int = line.paragraph.getAbsoluteStart();
+			var lineEnd:int = (line.absoluteStart + line.textLength) - paraStart;
+			var spanStart:int = element.getAbsoluteStart() - paraStart;		// get start pos relative to the paragraph (which might not be the parent)
+			var endPos:int = spanStart + element.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 = element.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 */
+		static public function calculateStrikeThrough(element:IFlowLeafElement, textLine:ITextLine, blockProgression:String, metrics:FontMetrics):Number
+		{
+			if(element.className == "InlineGraphicElement" && IInlineGraphicElement(element).graphic && IInlineGraphicElement(element).status == InlineGraphicElementStatus.READY)
+				return calculateGraphicStrikeThrough(IInlineGraphicElement(element), textLine, blockProgression, metrics);
+			else
+				return calculateLeafStrikeThrough(element, textLine, blockProgression, metrics);
+			
+		}
+		/**
+		 * @flexjsignorecoercion org.apache.flex.core.IParentIUIBase
+		 * @flexjsignorecoercion org.apache.flex.textLayout.compose.ITextFlowLine
+		 */
+		static private function calculateGraphicStrikeThrough(element:IInlineGraphicElement, textLine:ITextLine, blockProgression:String, metrics:FontMetrics):Number
+		{
+			var stOffset:Number = 0;
+            var inlineHolder:IParentIUIBase = element.placeholderGraphic.parent as IParentIUIBase;
+            if (inlineHolder)
+            {
+                if(blockProgression != BlockProgression.RL)
+                    stOffset = Object(element.placeholderGraphic.parent).y + (element.elementHeight/2 + Number(element.getEffectivePaddingTop()));
+                else
+                {
+                    var paddingRight:Number = element.getEffectivePaddingRight();
+                    var line:ITextFlowLine = textLine.userData as ITextFlowLine;
+                    var elemIdx:int = element.getAbsoluteStart() - line.absoluteStart;
+                    if(textLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
+                        stOffset = Object(element.placeholderGraphic.parent).x - (element.elementHeight/2 + paddingRight);
+                    else
+                        stOffset = Object(element.placeholderGraphic.parent).x - (element.elementWidth/2 + paddingRight);
+                }
+            }
+            
+            return blockProgression == BlockProgression.TB ? stOffset : -stOffset;
+		}
+		static private function calculateLeafStrikeThrough(element:IFlowLeafElement, textLine:ITextLine, blockProgression:String, metrics:FontMetrics):Number
+		{
+			var underlineAndStrikeThroughShift:int = 0;	
+			var effectiveFontSize:Number = element.getEffectiveFontSize();
+			if (element.computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
+			{
+				underlineAndStrikeThroughShift = -(metrics.superscriptOffset * effectiveFontSize);
+			} else if (element.computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
+			{
+				underlineAndStrikeThroughShift = -(metrics.subscriptOffset * (effectiveFontSize / metrics.subscriptScale));
+			} else {
+				underlineAndStrikeThroughShift = TextLayoutFormat.baselineShiftProperty.computeActualPropertyValue(element.computedFormat.baselineShift, effectiveFontSize);
+			}
+			
+			//grab the dominantBaseline and alignmentBaseline strings
+			var domBaselineString:String = GeometricElementUtils.resolveDomBaseline(element.computedFormat, element.getParagraph());
+			var alignmentBaselineString:String = element.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 != org.apache.flex.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 == org.apache.flex.text.engine.TextBaseline.IDEOGRAPHIC_CENTER)
+			{
+				stOffset = 0;
+			}
+			else if(domBaselineString == org.apache.flex.text.engine.TextBaseline.IDEOGRAPHIC_TOP || 
+				domBaselineString == org.apache.flex.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 == org.apache.flex.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM || 
+				domBaselineString == org.apache.flex.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 return number of shapes added */
+		static public function updateAdornments(element:IFlowLeafElement, tLine:ITextLine, blockProgression:String):int
+		{
+			CONFIG::debug { assert(element.computedFormat != null,"invalid call to updateAdornments"); }
+			
+			// Don't underline for floats
+			if(element.className == "InlineGraphicElement" && Object(element).effectiveFloat != Float.NONE)
+				return 0;
+			if(element.className == "TableLeafElement")
+				return 0;
+
+			// Only work on lines with strikethrough or underline
+			if (element.computedFormat.textDecoration == TextDecoration.UNDERLINE || element.computedFormat.lineThrough || element.computedFormat.backgroundAlpha > 0 && element.computedFormat.backgroundColor != BackgroundColor.TRANSPARENT)
+			{
+				var spanBoundsArray:Array = getSpanBoundsOnLine(element, tLine, blockProgression);
+				for (var i:int = 0; i < spanBoundsArray.length; i++)
+					updateAdornmentsOnBounds(element, tLine, blockProgression, spanBoundsArray[i]);
+				return spanBoundsArray.length ;
+			}
+			return 0;
+		}
+		
+		/**
+		 * @flexjsignorecoercion org.apache.flex.textLayout.elements.IParagraphElement
+		 */
+		static private function updateAdornmentsOnBounds(element:IFlowLeafElement, tLine:ITextLine, blockProgression:String, spanBounds:Rectangle):void
+		{
+			CONFIG::debug { assert(element.computedFormat != null,"invalid call to updateAdornmentsOnBounds"); }
+
+			var metrics:FontMetrics = element.getComputedFontMetrics();
+
+
+			var backgroundOnly:Boolean = !(element.computedFormat.textDecoration == TextDecoration.UNDERLINE || element.computedFormat.lineThrough);
+				
+			if (!backgroundOnly)
+			{
+				var shape:ICompoundGraphic;
+				shape = element.getTextFlow().tlfFactory.getCompoundGraphic();
+				shape.alpha = Number(element.computedFormat.textAlpha);
+				var builder:PathBuilder = new PathBuilder();
+				shape.stroke = new SolidColorStroke();
+						
+				var stOffset:Number = calculateStrikeThrough(element,tLine, blockProgression, metrics);
+				var ulOffset:Number = calculateUnderlineOffset(element, stOffset, blockProgression, metrics, tLine);
+			}
+						
+			if (blockProgression != BlockProgression.RL)
+			{
+				addBackgroundRect (element, tLine, metrics, spanBounds, true); 
+
+				if (element.computedFormat.textDecoration == TextDecoration.UNDERLINE)
+				{
+					shape.stroke.setLineStyle(metrics.underlineThickness, element.computedFormat.color as uint);
+					builder.moveTo(spanBounds.topLeft.x, ulOffset);
+					builder.lineTo(spanBounds.topLeft.x + spanBounds.width, ulOffset);
+					shape.drawPathCommands(builder);
+					builder.clear();
+//					g.lineStyle(metrics.underlineThickness, _computedFormat.color as uint);
+//					g.moveTo(spanBounds.topLeft.x, ulOffset);
+//					g.lineTo(spanBounds.topLeft.x + spanBounds.width, ulOffset);
+				}
+				
+				if((element.computedFormat.lineThrough))
+				{
+					shape.stroke.setLineStyle(metrics.strikethroughThickness, element.computedFormat.color as uint);
+					builder.moveTo(spanBounds.topLeft.x, stOffset);
+					builder.lineTo(spanBounds.topLeft.x + spanBounds.width, stOffset);
+					shape.drawPathCommands(builder);
+					builder.clear();
+					
+//					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:ITextFlowLine = tLine.userData as ITextFlowLine;
+				var elemIdx:int = element.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 (element, tLine, metrics, spanBounds, false);
+
+					if (element.computedFormat.textDecoration == TextDecoration.UNDERLINE)
+					{
+						shape.stroke.setLineStyle(metrics.underlineThickness, element.computedFormat.color as uint);
+						builder.moveTo(ulOffset, spanBounds.topLeft.y);
+						builder.lineTo(ulOffset, spanBounds.topLeft.y + spanBounds.height);
+						shape.drawPathCommands(builder);
+						builder.clear();
+						
+//						g.lineStyle(metrics.underlineThickness, _computedFormat.color as uint);
+//						g.moveTo(ulOffset, spanBounds.topLeft.y);
+//						g.lineTo(ulOffset, spanBounds.topLeft.y + spanBounds.height);
+					}
+					
+					if (element.computedFormat.lineThrough == true)
+					{
+						shape.stroke.setLineStyle(metrics.strikethroughThickness, element.computedFormat.color as uint);
+						builder.moveTo(-stOffset, spanBounds.topLeft.y);
+						builder.lineTo(-stOffset, spanBounds.topLeft.y + spanBounds.height);
+						shape.drawPathCommands(builder);
+						builder.clear();
+	
+//						g.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint);
+//						g.moveTo(-stOffset, spanBounds.topLeft.y);
+//						g.lineTo(-stOffset, spanBounds.topLeft.y + spanBounds.height);															
+					}
+				}
+				else
+				{
+					addBackgroundRect (element, tLine, metrics, spanBounds, true, true); 
+					
+					if (!backgroundOnly)
+					{
+						//it is TCY!
+						var tcyParent:ITCYElement =  element.getParentByType("TCYElement") as ITCYElement;
+						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:IParagraphElement = element.getParentByType("ParagraphElement") as IParagraphElement;
+						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((element.getAbsoluteStart() + element.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
+						{
+							var tcyAdornBounds:Rectangle = new Rectangle();
+							calculateAdornmentBounds(tcyParent, tLine, blockProgression, tcyAdornBounds);
+							
+							if (element.computedFormat.textDecoration == TextDecoration.UNDERLINE)
+							{
+								shape.stroke.setLineStyle(metrics.underlineThickness, element.computedFormat.color as uint);
+//								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;
+								
+								builder.moveTo(xCoor + baseULAdjustment, tcyAdornBounds.top);
+								builder.lineTo(xCoor + baseULAdjustment, tcyAdornBounds.bottom);
+								shape.drawPathCommands(builder);
+								builder.clear();
+								
+//								g.moveTo(xCoor + baseULAdjustment, tcyAdornBounds.top);
+//								g.lineTo(xCoor + baseULAdjustment, tcyAdornBounds.bottom);
+							}
+	
+							if (element.computedFormat.lineThrough == true)
+							{
+								var tcyMid:Number = spanBounds.bottomRight.x - tcyAdornBounds.x;
+								tcyMid /= 2;
+								tcyMid += tcyAdornBounds.x;
+								
+								shape.stroke.setLineStyle(metrics.strikethroughThickness, element.computedFormat.color as uint);
+								builder.moveTo(tcyMid, tcyAdornBounds.top);
+								builder.lineTo(tcyMid, tcyAdornBounds.bottom);
+								shape.drawPathCommands(builder);
+								builder.clear();
+								
+//								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 ITextLine. 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 ITextLine and passed it in as tLine so that we have correct metrics 
+			// for generating the adornment shapes.
+			if (shape)
+			{
+	 			var peekLine:ITextLine = (tLine.userData as ITextFlowLine).peekTextLine();
+				CONFIG::debug{ assert(peekLine == null || peekLine == tLine || peekLine.validity == "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.addElement(shape);
+			}
+		}
+		
+		/**
+		 * @flexjsignorecoercion org.apache.flex.textLayout.compose.ITextFlowLine
+		 */
+		public static function updateIMEAdornments(element:IFlowLeafElement,tLine:ITextLine, blockProgression:String, imeStatus:String):void
+		{
+			// Don't underline for floats
+			if(element.className == "InlineGraphicElement" && Object(element).effectiveFloat != Float.NONE)
+				return;
+
+			if(element.className == "TableLeafElement")
+				return ;
+
+			var metrics:FontMetrics = element.getComputedFontMetrics();
+			var spanBoundsArray:Array = getSpanBoundsOnLine(element,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(element, tLine, blockProgression, metrics);
+				var ulOffset:Number = calculateUnderlineOffset(element, 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:ITextFlowLine = tLine.userData as ITextFlowLine;
+					var elemIdx:int = element.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:ITCYElement =  element.getParentByType("TCYElement") as ITCYElement;
+						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((element.getAbsoluteStart() + element.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
+						{
+							var tcyAdornBounds:Rectangle = new Rectangle();	// NO PMD
+							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:ICompoundGraphic = element.getTextFlow().tlfFactory.getCompoundGraphic();	// NO PMD
+				//TODO - this is probably going to need to be overridable in the full implementation
+				selObj.alpha = 1;
+				selObj.fill = new SolidColor(imeLineColor);
+//				selObj.graphics.beginFill(imeLineColor);
+				
+				selObj.stroke = new SolidColorStroke(imeLineColor,imeLineThickness,selObj.alpha);
+//				selObj.graphics.lineStyle(imeLineThickness, imeLineColor, selObj.alpha);
+//				selObj.graphics.moveTo(imeLineStartX, imeLineStartY);
+//				selObj.graphics.lineTo(imeLineEndX, imeLineEndY);
+				var builder:PathBuilder = new PathBuilder(true);
+				builder.moveTo(imeLineStartX, imeLineStartY);
+				builder.lineTo(imeLineEndX, imeLineEndY);
+				selObj.drawPathCommands(builder);
+//				selObj.graphics.endFill();
+				tLine.addElement(selObj);
+			}
+		}
+	
+		static public function calculateUnderlineOffset(element:IFlowLeafElement, stOffset:Number, blockProgression:String, metrics:FontMetrics, textLine:ITextLine):Number
+		{
+			if(element.className == "InlineGraphicElement" && IInlineGraphicElement(element).graphic && IInlineGraphicElement(element).status == InlineGraphicElementStatus.READY)
+				return calculateGraphicUnderlineOffset(IInlineGraphicElement(element), stOffset, blockProgression, metrics, textLine);
+			else
+				return calculateLeafUnderlineOffset(element, stOffset, blockProgression, metrics, textLine);
+		
+		}
+		
+		static private function calculateLeafUnderlineOffset(element:IFlowLeafElement, stOffset:Number, blockProgression:String, metrics:FontMetrics, textLine:ITextLine):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:IParagraphElement = element.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 
+         *  @flexjsignorecoercion org.apache.flex.core.IParentIUIBase
+         */
+        static private function calculateGraphicUnderlineOffset(element:IInlineGraphicElement, stOffset:Number, blockProgression:String, metrics:FontMetrics, tLine:ITextLine):Number
+        {
+            var para:IParagraphElement = element.getParagraph();
+            var ulOffset:Number = 0;
+            var inlineHolder:IParentIUIBase = element.placeholderGraphic.parent as IParentIUIBase;
+            if (inlineHolder)
+            {
+                if(blockProgression == BlockProgression.TB)
+                    ulOffset = inlineHolder.y + element.elementHeightWithMarginsAndPadding();
+                else
+                {                   
+                    if (para.computedFormat.locale.toLowerCase().indexOf("zh") == 0)
+                    {
+                        ulOffset = inlineHolder.x - element.elementHeightWithMarginsAndPadding();
+                        ulOffset -= metrics.underlineOffset + (metrics.underlineThickness/2);
+                        return ulOffset;
+                    }
+                    else
+                        ulOffset = inlineHolder.x - element.getEffectivePaddingLeft();
+                }
+            }   
+            ulOffset += metrics.underlineOffset + (metrics.underlineThickness/2);
+            
+            var justRule:String = para.getEffectiveJustificationRule();
+            if(justRule == JustificationRule.EAST_ASIAN)
+                ulOffset += 1;
+        
+            return ulOffset;
+        }
+		
+				/** @private
+		 * Adds the background rectangle (if needed), making adjustments for glyph shifting as appropriate
+		 */
+		 static private function addBackgroundRect(element:IFlowLeafElement, tLine:ITextLine, metrics:FontMetrics, spanBounds:Rectangle, horizontalText:Boolean, isTCY:Boolean=false):void
+		 {
+			if(element.computedFormat.backgroundAlpha == 0 || element.computedFormat.backgroundColor == BackgroundColor.TRANSPARENT)
+				return;
+				
+			var tf:ITextFlow = element.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 && (element.computedFormat.baselineShift == BaselineShift.SUPERSCRIPT || element.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 = element.getEffectiveFontSize();
+				var baseStrikethroughOffset:Number = metrics.strikethroughOffset + metrics.strikethroughThickness/2;
+				
+				if (element.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, element, r, element.computedFormat.backgroundColor, element.computedFormat.backgroundAlpha);	 
+		}
+		
+				/**
+		 *  @private
+		 *  @flexjsignorecoercion org.apache.flex.core.IUIBase
+		 *  @flexjsignorecoercion org.apache.flex.textLayout.elements.IFlowLeafElement
+		 */
+		static public function calculateAdornmentBounds(spg:ISubParagraphGroupElementBase, tLine:ITextLine, blockProgression:String, spgRect:Rectangle):void
+		{
+			var childCount:int = 0;
+			while(childCount < spg.numChildren)
+			{
+				var curChild:IFlowElement = spg.getChildAt(childCount) as IFlowElement;
+				var curFlowLeaf:IFlowLeafElement = curChild as IFlowLeafElement;
+				if(!curFlowLeaf && curChild is ISubParagraphGroupElementBase)
+				{
+					calculateAdornmentBounds(curChild as ISubParagraphGroupElementBase, tLine, blockProgression, spgRect);
+					++childCount;
+					continue;
+				}
+				
+				CONFIG::debug{ assert(curFlowLeaf != null, "The TCY contains a non-FlowLeafElement!  Cannot calculate mirror!");}
+				var curBounds:Rectangle = null;
+				if(!(curFlowLeaf is IInlineGraphicElement))
+					curBounds = getSpanBoundsOnLine(curFlowLeaf, tLine, blockProgression)[0];
+				else
+				{
+					curBounds = BoundsUtil.getBounds(curFlowLeaf as IUIBase, tLine);// (curFlowLeaf as InlineGraphicElement).graphic.getBounds(tLine);
+				}
+				
+				if(childCount != 0)
+				{
+					if(curBounds.top < spgRect.top)
+						spgRect.top = curBounds.top;
+						
+					if(curBounds.bottom > spgRect.bottom)
+						spgRect.bottom = curBounds.bottom;
+					
+					if(spgRect.x > curBounds.x)
+						spgRect.x = curBounds.x;
+				}
+				else
+				{
+					spgRect.top = curBounds.top;
+					spgRect.bottom = curBounds.bottom;
+					spgRect.x = curBounds.x;
+				}
+				++childCount;
+			}
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/ContextUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/ContextUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/ContextUtil.as
new file mode 100644
index 0000000..5feb5b1
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/ContextUtil.as
@@ -0,0 +1,31 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.compose.ISWFContext;
+
+	public class ContextUtil
+	{
+				/** @private - helper function for finding a base swf context from a swf context */
+		public static function computeBaseSWFContext(context:ISWFContext):ISWFContext
+		{
+			return context && Object(context).hasOwnProperty("getBaseSWFContext") ? context["getBaseSWFContext"]() : context;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/FactoryHelper.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/FactoryHelper.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/FactoryHelper.as
new file mode 100644
index 0000000..4bb96b4
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/FactoryHelper.as
@@ -0,0 +1,36 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.compose.IFactoryComposer;
+	import org.apache.flex.textLayout.compose.ISimpleCompose;
+	import org.apache.flex.textLayout.utils.FactoryUtil;
+	public class FactoryHelper
+	{
+		static public function getComposer():IFactoryComposer
+		{
+			if(!composerClass)
+				composerClass = FactoryUtil.getDefaultFlowComposerClass();
+
+			return new composerClass();
+		}
+		static public var composerClass:Class;
+		static public var staticComposer:ISimpleCompose;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberLineUserData.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberLineUserData.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberLineUserData.as
new file mode 100644
index 0000000..831c753
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberLineUserData.as
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.elements.IBackgroundManager;
+	import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+
+	public class NumberLineUserData
+	{
+		public function NumberLineUserData(listStylePosition:String, insideLineWidth:Number, spanFormat:ITextLayoutFormat, paraDirection:String)
+		{
+			this.listStylePosition = listStylePosition;
+			// added by yong
+			this.insideLineWidth = insideLineWidth;
+			this.spanFormat = spanFormat;
+			this.paragraphDirection = paraDirection;
+		}
+
+		public var listStylePosition:String;
+		public var insideLineWidth:Number;
+		public var spanFormat:ITextLayoutFormat;
+		public var paragraphDirection:String;
+		public var listEndIndent:Number;
+		public var backgroundManager:IBackgroundManager;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberlineUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberlineUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberlineUtil.as
new file mode 100644
index 0000000..d82bca3
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/NumberlineUtil.as
@@ -0,0 +1,160 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.utils.NumberFactoryUtil;
+	import org.apache.flex.core.UIBase;
+	import org.apache.flex.geom.Rectangle;
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.textLayout.compose.ISWFContext;
+	import org.apache.flex.textLayout.compose.SWFContext;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.ILinkElement;
+	import org.apache.flex.textLayout.elements.IListElement;
+	import org.apache.flex.textLayout.elements.IListItemElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.LinkState;
+	import org.apache.flex.textLayout.factory.INumberLineFactory;
+	import org.apache.flex.textLayout.formats.Direction;
+	import org.apache.flex.textLayout.formats.FormatValue;
+	import org.apache.flex.textLayout.formats.IListMarkerFormat;
+	import org.apache.flex.textLayout.formats.ListStylePosition;
+	import org.apache.flex.textLayout.formats.TextLayoutFormat;
+
+	public class NumberlineUtil
+	{
+		static private var numberLineFactory:INumberLineFactory;
+
+		/**
+		*
+		* @private Logic to generate and position the ITextLine containing the numbering for a listElement's first line 
+		* @flexjsignorecoercion org.apache.flex.textLayout.elements.ILinkElement
+		* @flexjsignorecoercion org.apache.flex.textLayout.elements.IListElement
+		 */
+		static public function createNumberLine(listItemElement:IListItemElement, curParaElement:IParagraphElement, swfContext:ISWFContext, totalStartIndent:Number):ITextLine
+		{
+			CONFIG::debug
+			{
+				assert(swfContext != SWFContext.globalSWFContext, "TextFlowLine.createNumberLine: don't pass globalswfcontext"); }
+			if (numberLineFactory == null)
+			{
+				numberLineFactory = NumberFactoryUtil.getNumberFactory();
+				numberLineFactory.compositionBounds = new Rectangle(0, 0, NaN, NaN);
+			}
+			numberLineFactory.swfContext = swfContext;
+
+			var listMarkerFormat:IListMarkerFormat = listItemElement.computedListMarkerFormat();
+
+			// use the listStylePosition on the ListItem (not the list)
+			numberLineFactory.listStylePosition = listItemElement.computedFormat.listStylePosition;
+
+			var listElement:IListElement = listItemElement.parent as IListElement;
+			var paragraphFormat:TextLayoutFormat = new TextLayoutFormat(curParaElement.computedFormat);
+			var boxStartIndent:Number = paragraphFormat.direction == Direction.LTR ? listElement.getEffectivePaddingLeft() + listElement.getEffectiveBorderLeftWidth() + listElement.getEffectiveMarginLeft() : listElement.getEffectivePaddingRight() + listElement.getEffectiveBorderRightWidth() + listElement.getEffectiveMarginRight();
+			// this just gets the first line but that's the only one we use.  could have used paragraphStartIndent or padding/margins.
+			// do it this way so that negative indents are supported.  TODO revisit when box model work is complete
+			paragraphFormat.apply(listMarkerFormat);
+			// Fix bug 2800975 ListMarkerFormat.paragraphStartIndent not applied properly in Inside lists.
+			paragraphFormat.textIndent += totalStartIndent;
+			if (numberLineFactory.listStylePosition == ListStylePosition.OUTSIDE)
+				paragraphFormat.textIndent -= boxStartIndent;
+			numberLineFactory.paragraphFormat = paragraphFormat; // curParaElement.computedFormat;
+			numberLineFactory.textFlowFormat = curParaElement.getTextFlow().computedFormat;
+
+			// suppress the formatting of any links
+			var firstLeaf:IFlowLeafElement = curParaElement.getFirstLeaf();
+			var parentLink:ILinkElement = firstLeaf.getParentByType("LinkElement") as ILinkElement;
+			// record the topmost parent link
+			var highestParentLinkLinkElement:ILinkElement;
+			var linkStateArray:Array = [];
+			while (parentLink)
+			{
+				highestParentLinkLinkElement = parentLink;
+				linkStateArray.push(parentLink.linkState);
+				parentLink.chgLinkState(LinkState.SUPPRESSED);
+				parentLink = parentLink.getParentByType("LinkElement") as ILinkElement;
+			}
+
+			// spanFormat to use for the markers
+			var spanFormat:TextLayoutFormat = new TextLayoutFormat(firstLeaf.computedFormat);
+
+			// now restore the formatting of any links
+			parentLink = firstLeaf.getParentByType("LinkElement") as ILinkElement;
+			while (parentLink)
+			{
+				linkStateArray.push(parentLink.linkState);
+				parentLink.chgLinkState(linkStateArray.shift());
+				parentLink = parentLink.getParentByType("LinkElement") as ILinkElement;
+			}
+
+			// forces recompute of computedFormat of all leaf nodes of highestParentLinkLinkElement
+			if (highestParentLinkLinkElement)
+			{
+				var leaf:IFlowLeafElement = highestParentLinkLinkElement.getFirstLeaf();
+				while (leaf)
+				{
+					leaf.calculateComputedFormat();
+					leaf = leaf.getNextLeaf(highestParentLinkLinkElement);
+				}
+			}
+
+			// finalize the spanFormat for the marker
+			var markerFormat:TextLayoutFormat = new TextLayoutFormat(spanFormat);
+			TextLayoutFormat.resetModifiedNoninheritedStyles(markerFormat);
+			var holderStyles:Object = (listMarkerFormat as TextLayoutFormat).getStyles();
+			for (var key:String in holderStyles)
+			{
+				// only copy TextLayoutFormat properties
+				if (TextLayoutFormat.description[key] !== undefined)
+				{
+					var val:* = holderStyles[key];
+					markerFormat[key] = (val !== FormatValue.INHERIT) ? val : spanFormat[key];
+				}
+			}
+			numberLineFactory.markerFormat = markerFormat;
+			numberLineFactory.text = listElement.computeListItemText(listItemElement, listMarkerFormat);
+
+			// expect one or zero lines - technically with beforeContent and afterContent more than one line can be generated.  This could be more like a float!!
+			// also need to expect a backgroundColor
+			var rslt:Array = [];
+			numberLineFactory.createTextLines(function(o:UIBase):void
+			{
+				rslt.push(o);
+			});
+
+			// position it relative to the parent line - later need to take inside/outside into account
+			var numberLine:ITextLine = rslt[0] as ITextLine;
+			if (numberLine)
+			{
+				CONFIG::debug
+				{
+					assert(numberLine.validity == "static", "Invalid validity on numberLine"); }
+				// TODO deal with mouseEnabled and mouseChildren
+				// numberLine.mouseEnabled = false;
+				// numberLine.mouseChildren = false;
+				TextLineUtil.setNumberLineBackground(numberLine, numberLineFactory.backgroundManager);
+			}
+			numberLineFactory.clearBackgroundManager();
+
+			return numberLine;
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/StandardHelper.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/StandardHelper.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/StandardHelper.as
new file mode 100644
index 0000000..c197b22
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/StandardHelper.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.textLayout.compose.IFlowComposer;
+	import org.apache.flex.textLayout.compose.StandardFlowComposer;
+
+	public class StandardHelper
+	{
+		static public function getStandardClass():Class
+		{
+			return StandardFlowComposer;
+		}
+		static public function getNewComposer():IFlowComposer
+		{
+			return new StandardFlowComposer();
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/TextLineUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/TextLineUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/TextLineUtil.as
new file mode 100644
index 0000000..52a0bd2
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/utils/TextLineUtil.as
@@ -0,0 +1,172 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.compose.utils
+{
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.elements.IBackgroundManager;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.IInlineGraphicElement;
+	import org.apache.flex.textLayout.elements.IListItemElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.formats.BlockProgression;
+	import org.apache.flex.textLayout.formats.Direction;
+	import org.apache.flex.textLayout.formats.FormatValue;
+	import org.apache.flex.textLayout.formats.IListMarkerFormat;
+	import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+	import org.apache.flex.textLayout.formats.ListStylePosition;
+
+	public class TextLineUtil
+	{
+		/** @private */
+		static public function findNumberLine(textLine:ITextLine):ITextLine
+		{
+			if (textLine == null)
+				return null;
+			// not always going to be a numberLine - listStyleType may be "none"
+			// have to hunt for it because inlinegraphics get pushed at the beginning
+			// risk here is that clients decorate TextLines with other TextLines.
+			for (var idx:int = 0; idx < textLine.numElements; idx++)
+			{
+				var numberLine:ITextLine = textLine.getElementAt(idx) as ITextLine;
+				if (numberLine && (numberLine.userData is NumberLineUserData))
+					break;
+			}
+			return numberLine;
+		}
+
+		/** @private */
+		static public function getNumberLineListStylePosition(numberLine:ITextLine):String
+		{
+			return (numberLine.userData as NumberLineUserData).listStylePosition;
+		}
+
+		/** @private */
+		static public function getNumberLineInsideLineWidth(numberLine:ITextLine):Number
+		{
+			return (numberLine.userData as NumberLineUserData).insideLineWidth;
+		}
+
+		/** @private */
+		static public function getNumberLineSpanFormat(numberLine:ITextLine):ITextLayoutFormat
+		{
+			return (numberLine.userData as NumberLineUserData).spanFormat;
+		}
+
+		/** @private */
+		static public function getNumberLineParagraphDirection(numberLine:ITextLine):String
+		{
+			return (numberLine.userData as NumberLineUserData).paragraphDirection;
+		}
+
+		/** @private */
+		static public function setListEndIndent(numberLine:ITextLine, listEndIndent:Number):void
+		{
+			(numberLine.userData as NumberLineUserData).listEndIndent = listEndIndent;
+		}
+
+		/** @private */
+		static public function getListEndIndent(numberLine:ITextLine):Number
+		{
+			return (numberLine.userData as NumberLineUserData).listEndIndent;
+		}
+
+		/** @private */
+		static public function setNumberLineBackground(numberLine:ITextLine, background:IBackgroundManager):void
+		{
+			(numberLine.userData as NumberLineUserData).backgroundManager = background;
+		}
+
+		/** @private */
+		static public function getNumberLineBackground(numberLine:ITextLine):IBackgroundManager
+		{
+			return (numberLine.userData as NumberLineUserData).backgroundManager;
+		}
+
+		/** @private */
+		static public function initializeNumberLinePosition(numberLine:ITextLine, listItemElement:IListItemElement, curParaElement:IParagraphElement, totalWidth:Number):void
+		{
+			// use the listStylePosition on the ListItem (not the list)
+			var listMarkerFormat:IListMarkerFormat = listItemElement.computedListMarkerFormat();
+			var paragraphFormat:ITextLayoutFormat = curParaElement.computedFormat;
+			// only applies on outside list markers
+			var listEndIndent:Number = listMarkerFormat.paragraphEndIndent === undefined || listItemElement.computedFormat.listStylePosition == ListStylePosition.INSIDE ? 0 : (listMarkerFormat.paragraphEndIndent == FormatValue.INHERIT ? paragraphFormat.paragraphEndIndent : listMarkerFormat.paragraphEndIndent);
+
+			TextLineUtil.setListEndIndent(numberLine, listEndIndent);
+
+			// no more work needed for OUTSIDE positioning - its all done in the applyTextAlign code
+			if (listItemElement.computedFormat.listStylePosition == ListStylePosition.OUTSIDE)
+			{
+				numberLine.x = numberLine.y = 0;
+				return;
+			}
+
+			var bp:String = curParaElement.getTextFlow().computedFormat.blockProgression;
+			var numberLineWidth:Number = TextLineUtil.getNumberLineInsideLineWidth(numberLine);
+
+			if (bp == BlockProgression.TB)
+			{
+				if (paragraphFormat.direction == Direction.LTR)
+					numberLine.x = -numberLineWidth;
+				else
+					numberLine.x = totalWidth + numberLineWidth - numberLine.textWidth;
+				numberLine.y = 0;	// assumes same baseline as parent!!
+			}
+			else
+			{
+				if (paragraphFormat.direction == Direction.LTR)
+					numberLine.y = -numberLineWidth;
+				else
+					numberLine.y = totalWidth + numberLineWidth - numberLine.textWidth;
+				numberLine.x = 0;	// assumes same baseline as parent!!
+			}
+		}
+
+		/** @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 public function getTextLineTypographicAscent(textLine:ITextLine, elem:IFlowLeafElement, elemStart:int, textLineEnd:int):Number
+		{
+			CONFIG::debug
+			{
+				assert(!elem || elemStart == elem.getAbsoluteStart(), "bad elemStart passed to getTextLineTypographicAscent"); }
+			var rslt:Number = textLine.getBaselinePosition(org.apache.flex.text.engine.TextBaseline.ROMAN) - textLine.getBaselinePosition(org.apache.flex.text.engine.TextBaseline.ASCENT);
+
+			if (textLine.hasGraphicElement)
+			{
+				for (;;)
+				{
+					if (elem is IInlineGraphicElement)
+						rslt = Math.max(rslt, IInlineGraphicElement(elem).getTypographicAscent(textLine));
+					elemStart += elem.textLength;
+					if (elemStart >= textLineEnd)
+						break;
+					elem = elem.getNextLeaf();
+					CONFIG::debug
+					{
+						assert(elem != null, "bad nextLeaf"); }
+				}
+			}
+			return rslt;
+		}
+
+	}
+}
\ No newline at end of file


Mime
View raw message