You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ha...@apache.org on 2017/03/16 13:37:55 UTC
[35/42] flex-asjs git commit: And here’s TLF…
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