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:58 UTC
[38/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/ITextFlowLine.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowLine.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowLine.as
new file mode 100644
index 0000000..6fe88e8
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowLine.as
@@ -0,0 +1,104 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.core.IParentIUIBase;
+ import org.apache.flex.geom.Rectangle;
+ import org.apache.flex.graphics.ICompoundGraphic;
+ import org.apache.flex.text.engine.ITextBlock;
+ import org.apache.flex.text.engine.ITextLine;
+ import org.apache.flex.textLayout.container.IContainerController;
+ import org.apache.flex.textLayout.edit.SelectionFormat;
+ import org.apache.flex.textLayout.elements.IFlowLeafElement;
+ import org.apache.flex.textLayout.elements.IParagraphElement;
+ import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+
+ public interface ITextFlowLine extends IVerticalJustificationLine
+ {
+ function get composable():Boolean;
+ function initialize(paragraph:IParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0, textLine:ITextLine = null):void;
+ function get heightTW():int;
+ function get outerTargetWidthTW():int;
+ function get ascentTW():int;
+ function get targetWidthTW():int;
+ function get textHeightTW():int;
+ function get lineOffsetTW():int;
+ function get lineExtentTW():int;
+ function get hasGraphicElement():Boolean;
+ function get hasNumberLine():Boolean;
+ function get numberLinePosition():Number;
+ function set numberLinePosition(position:Number):void;
+ function get textHeight():Number ;
+ function get xTW():int;
+ function get yTW():int;
+ function setXYAndHeight(lineX:Number,lineY:Number,lineHeight:Number):void;
+ function get location():int;
+ function get controller():IContainerController;
+ function get columnIndex():int;
+ function setController(cont:IContainerController,colNumber:int):void;
+ function get lineOffset():Number;
+ function get paragraph():IParagraphElement;
+ function get absoluteStart():int;
+ function setAbsoluteStart(val:int):void;
+ function get textLength():int;
+ function setTextLength(val:int):void;
+ function get spaceBefore():Number;
+ function get spaceAfter():Number;
+ function get outerTargetWidth():Number;
+ function set outerTargetWidth(val:Number):void;
+ function get targetWidth():Number;
+ function getBounds():Rectangle;
+ function get validity():String;
+ function get unjustifiedTextWidth():Number;
+ function get lineExtent():Number;
+ function set lineExtent(value:Number):void;
+ function get accumulatedLineExtent():Number;
+ function set accumulatedLineExtent(value:Number):void;
+ function get accumulatedMinimumStart():Number;
+ function set accumulatedMinimumStart(value:Number):void;
+ function get alignment():String;
+ function set alignment(value:String):void;
+ function isDamaged():Boolean;
+ function clearDamage():void;
+ function damage(damageType:String):void;
+ function testLineVisible(wmode:String, x:int, y:int, w:int, h:int):int;
+ function oldTestLineVisible(wmode:String, x:int, y:int, w:int, h:int):Boolean;
+ function cacheLineBounds(wmode:String, bndsx:Number, bndsy:Number, bndsw:Number, bndsh:Number):void;
+ function hasLineBounds():Boolean;
+ function get textLineExists():Boolean;
+ function peekTextLine():ITextLine;
+ function getTextLine(forceValid:Boolean = false):ITextLine;
+ function recreateTextLine(textBlock:ITextBlock, previousLine:ITextLine):ITextLine;
+ function createShape(bp:String, textLine:ITextLine):void;
+ function createAdornments(blockProgression:String,elem:IFlowLeafElement,elemStart:int, textLine:ITextLine, numberLine:ITextLine):void;
+ function getLineLeading(bp:String,elem:IFlowLeafElement,elemStart:int):Number;
+ function getLineTypographicAscent(elem:IFlowLeafElement,elemStart:int,textLine:ITextLine):Number;
+ function getCSSLineBox(bp:String, elem:IFlowLeafElement, elemStart:int, swfContext:ISWFContext, effectiveListMarkerFormat:ITextLayoutFormat=null, numberLine:ITextLine=null):Rectangle;
+ function calculateSelectionBounds(textLine:ITextLine, rectArray:Array, begIdx:int, endIdx:int, blockProgression:String, heightAndAdj:Array):void;
+ function getRomanSelectionHeightAndVerticalAdjustment (prevLine:ITextFlowLine, nextLine:ITextFlowLine):Array;
+ function convertLineRectToContainer(rect:Rectangle, constrainShape:Boolean):void;
+ function hiliteBlockSelection(selObj:ICompoundGraphic, selFormat:SelectionFormat, container:IParentIUIBase, begIdx:int,endIdx:int, prevLine:ITextFlowLine, nextLine:ITextFlowLine):void;
+ function hilitePointSelection(selFormat:SelectionFormat, idx:int, container:IParentIUIBase, prevLine:ITextFlowLine, nextLine:ITextFlowLine):void;
+ function computePointSelectionRectangle(idx:int, container:IParentIUIBase, prevLine:ITextFlowLine, nextLine:ITextFlowLine, constrainSelRect:Boolean):Rectangle;
+ function selectionWillIntersectScrollRect(scrollRect:Rectangle, begIdx:int, endIdx:int, prevLine:ITextFlowLine, nextLine:ITextFlowLine):int;
+
+ function get adornCount():int ;
+
+ }
+}
\ 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/ITextFlowTableBlock.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowTableBlock.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowTableBlock.as
new file mode 100644
index 0000000..6ad273a
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ITextFlowTableBlock.as
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.elements.CellCoordinates;
+ import org.apache.flex.textLayout.elements.ITableElement;
+ import org.apache.flex.textLayout.elements.TableBlockContainer;
+ import org.apache.flex.textLayout.elements.CellContainer;
+ import org.apache.flex.textLayout.elements.ITableCellElement;
+ import org.apache.flex.textLayout.elements.TableCellElement;
+
+ public interface ITextFlowTableBlock extends ITextFlowLine
+ {
+ function clear():void;
+
+ function getTableCells():Vector.<ITableCellElement>;
+
+ function addCell(container:CellContainer):void;
+
+ function get container():TableBlockContainer
+
+ function get parentTable():ITableElement;
+
+ function updateCompositionShapes():void;
+
+ function set parentTable(parentTable:ITableElement):void;
+
+ function getCellsInRange(startCoords:CellCoordinates, endCoords:CellCoordinates):Vector.<ITableCellElement>;
+ }
+}
\ 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/IVerticalJustificationLine.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/IVerticalJustificationLine.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/IVerticalJustificationLine.as
new file mode 100644
index 0000000..ee6a315
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/IVerticalJustificationLine.as
@@ -0,0 +1,95 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.elements.IParagraphElement;
+ import org.apache.flex.text.engine.ITextLine;
+
+ /**
+ * The IVerticalJustificationLine interface defines the methods and properties required to allow
+ * the vertical justification of text lines.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ public interface IVerticalJustificationLine
+ {
+ /**
+ * The horizontal position of the line relative to its container, expressed as the offset in pixels from the
+ * left of the container.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see #y
+ */
+ function get x():Number;
+
+ /** Set X location for the line. Used only during vertical justification. @private */
+ function set x(val:Number):void;
+
+ /**
+ * The vertical position of the line relative to its container, expressed as the offset in pixels from the top
+ * of the container.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see #x
+ */
+ function get y():Number;
+
+ /** Set Y location for the line. Used only during vertical justification. @private */
+ function set y(val:Number):void;
+
+ /**
+ * @copy org.apache.flex.text.engine.TextLine#ascent
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ function get ascent():Number;
+
+ /**
+ * @copy org.apache.flex.text.engine.TextLine#descent
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ function get descent():Number;
+
+ /** The height of the line in pixels.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ function get height():Number;
+
+
+ // TODO for TextFlowTableBloack
+ function set height(value:Number):void;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Parcel.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Parcel.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Parcel.as
new file mode 100644
index 0000000..51fb80d
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Parcel.as
@@ -0,0 +1,376 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Constants;
+
+ import org.apache.flex.textLayout.container.IContainerController;
+// import org.apache.flex.textLayout.debug.assert;
+ import org.apache.flex.textLayout.formats.ClearFloats;
+ import org.apache.flex.textLayout.formats.Direction;
+
+
+
+
+ /**
+ * Helper class for implementations of IParcelList
+ *
+ * @private
+ */
+ public class Parcel
+ {
+ public var x:Number;
+ public var y:Number;
+ public var width:Number;
+ public var height:Number;
+ public var logicalWidth:Number;
+
+ private var _controller:IContainerController;
+ private var _columnIndex:int;
+ private var _fitAny:Boolean;
+ private var _composeToPosition:Boolean;
+
+ private var _left:Edge;
+ private var _right:Edge;
+ private var _maxWidth:Number;
+
+ private const EDGE_CACHE_MAX:int = 6; // number of edges we cache
+ static private var edgeCache:Vector.<Edge>; // cache to prevent edge allocation/deallocation
+
+ private var _verticalText:Boolean;
+
+ /** Constructor. */
+ public function Parcel(verticalText:Boolean, x:Number, y:Number, width:Number, height:Number, controller:IContainerController, columnIndex:int)
+ {
+ initialize(verticalText, x, y, width, height, controller, columnIndex);
+ }
+
+ public function initialize(verticalText:Boolean, x:Number, y:Number, width:Number, height:Number, controller:IContainerController, columnIndex:int):Parcel
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.logicalWidth = verticalText ? height : width;
+ this._verticalText = verticalText;
+
+ _controller = controller;
+ _columnIndex = columnIndex;
+ _fitAny = false;
+ _composeToPosition = false;
+
+ var xmin:Number;
+ if (verticalText)
+ {
+ xmin = y;
+ _maxWidth = height;
+ }
+ else
+ {
+ xmin = x;
+ _maxWidth = width;
+ }
+
+ _left = allocateEdge(xmin);
+ _right = allocateEdge(xmin + _maxWidth);
+ return this;
+ }
+
+
+ /** prevent any leaks. @private */
+ public function releaseAnyReferences():void
+ {
+ _controller = null;
+ deallocateEdge(_left);
+ deallocateEdge(_right);
+ }
+
+ private function allocateEdge(x:Number):Edge
+ {
+ if (!edgeCache)
+ edgeCache = new Vector.<Edge>();
+ var edge:Edge = (edgeCache.length > 0) ? edgeCache.pop() : new Edge();
+ edge.initialize(x);
+ return edge;
+ }
+
+ private function deallocateEdge(edge:Edge):void
+ {
+ if (edgeCache.length < EDGE_CACHE_MAX)
+ edgeCache.push(edge);
+ }
+
+ public function get bottom():Number { return (y + height); }
+ public function get right():Number { return (x + width); }
+
+ public function get controller():IContainerController
+ { return _controller; }
+
+ /** column number in the container */
+ public function get columnIndex():int
+ { return _columnIndex; }
+ public function get fitAny():Boolean
+ { return _fitAny; }
+ public function set fitAny(value:Boolean):void
+ { _fitAny = value; }
+ public function get composeToPosition():Boolean
+ { return _composeToPosition; }
+ public function set composeToPosition(value:Boolean):void
+ { _composeToPosition = value; }
+ /** Do explicit line breaking (no wrapping) */
+
+ private function getLogicalHeight():Number
+ {
+ if (_verticalText)
+ {
+ return _controller.measureWidth ? Constants.MAX_LINE_WIDTH : width;
+ }
+ else
+ {
+ return _controller.measureHeight ? Constants.MAX_LINE_WIDTH : height;
+ }
+ }
+
+ // Returns the amount to move down to apply clear past any floats
+ public function applyClear(clear:String, depth:Number, direction:String):Number
+ {
+ var leftMargin:Number;
+ var rightMargin:Number;
+ var adjustedDepth:Number = depth;
+
+ if (clear == ClearFloats.START)
+ clear = (direction == Direction.LTR) ? ClearFloats.LEFT : ClearFloats.RIGHT;
+ else if (clear == ClearFloats.END)
+ clear = (direction == Direction.RTL) ? ClearFloats.LEFT : ClearFloats.RIGHT;
+
+ while (adjustedDepth < Number.MAX_VALUE)
+ {
+ leftMargin = _left.getMaxForSpan(adjustedDepth, adjustedDepth + 1); // getLeftForSpan
+ if (leftMargin > 0 && (clear == ClearFloats.BOTH || clear == ClearFloats.LEFT))
+ {
+ adjustedDepth = _left.findNextTransition(adjustedDepth);
+ continue;
+ }
+ rightMargin = _right.getMaxForSpan(adjustedDepth, adjustedDepth + 1); // getRightForSpan
+ if (rightMargin > 0 && (clear == ClearFloats.BOTH || clear == ClearFloats.RIGHT))
+ {
+ adjustedDepth = _right.findNextTransition(adjustedDepth);
+ continue;
+ }
+
+ return adjustedDepth - depth;
+ }
+
+ return (_verticalText ? this.width : this.height);
+ }
+
+ public function fitsInHeight(depth:Number, minimumHeight:Number):Boolean
+ {
+ return composeToPosition || depth + minimumHeight <= getLogicalHeight();
+ }
+
+ // Given a current location, what is the longest longest line of a given height that can be placed there,
+ // that is at least as wide as the minimum width. Return false if there is no possible line in the parcel.
+ // May shift the line down if thee is more space below.
+ public function getLineSlug(slug:Slug, depth:Number, lineHeight:Number, minimumWidth:Number, minimumHeight:Number, leftMargin:Number, rightMargin:Number, textIndent:Number, directionLTR:Boolean, useExplicitLineBreaks:Boolean):Boolean
+ {
+ if (!fitsInHeight(depth, minimumHeight))
+ return false;
+
+ slug.height = lineHeight;
+
+ while (depth < Number.MAX_VALUE)
+ {
+ slug.depth = depth;
+
+ slug.leftMargin = _left.getMaxForSpan(slug.depth, slug.depth + lineHeight); // getLeftForSpan
+ slug.wrapsKnockOut = slug.leftMargin != 0;
+ if (leftMargin > 0)
+ slug.leftMargin = Math.max(leftMargin, slug.leftMargin);
+ else
+ slug.leftMargin += leftMargin; // negative indent, let it overlap
+ slug.rightMargin = _right.getMaxForSpan(slug.depth, slug.depth + lineHeight); // getRightForSpan
+ slug.wrapsKnockOut = slug.wrapsKnockOut || (slug.rightMargin != 0);
+ if (rightMargin > 0)
+ slug.rightMargin = Math.max(rightMargin, slug.rightMargin);
+ else
+ slug.rightMargin += rightMargin; // negative indent, let it overlap
+ if (textIndent)
+ {
+ if (directionLTR)
+ slug.leftMargin += textIndent;
+ else
+ slug.rightMargin += textIndent;
+ }
+
+ if (useExplicitLineBreaks || (_verticalText && _controller.measureHeight) || (!_verticalText && _controller.measureWidth))
+ slug.width = Constants.MAX_LINE_WIDTH;
+ else
+ slug.width = this.logicalWidth - (slug.leftMargin + slug.rightMargin);
+ if (!minimumWidth || slug.width >= minimumWidth)
+ break;
+ depth = findNextTransition(depth);
+ }
+
+ return (depth < Number.MAX_VALUE);
+ }
+
+ public function knockOut(knockOutWidth:Number, yMin:Number, yMax:Number, onLeft:Boolean):void
+ {
+ var edge:Edge = onLeft ? _left : _right;
+ edge.addSpan(knockOutWidth, yMin, yMax);
+ }
+
+ public function removeKnockOut(knockOutWidth:Number, yMin:Number, yMax:Number, onLeft:Boolean):void
+ {
+ var edge:Edge = onLeft ? _left : _right;
+ edge.removeSpan(knockOutWidth, yMin, yMax);
+ }
+
+ /** Returns true if the parcel has no knockouts */
+ public function isRectangular():Boolean
+ {
+ return (_left.numSpans <= 0 && _right.numSpans <= 0);
+ }
+
+ /* public function getLeftForSpan(ymin:Number, ymax:Number):Number
+ {
+ return _left.getMaxForSpan(ymin, ymax);
+ }
+
+ public function getRightForSpan(ymin:Number, ymax:Number):Number
+ {
+ return _right.getMinForSpan(ymin, ymax);
+ } */
+
+ public function findNextTransition(y:Number):Number
+ {
+ return Math.min(_left.findNextTransition(y), _right.findNextTransition(y));
+ }
+
+ }
+}
+
+class Span
+{
+ public var x:Number;
+ public var ymin:Number;
+ public var ymax:Number;
+
+ public function Span(x:Number, ymin:Number, ymax:Number)
+ {
+ this.x = x;
+ this.ymin = ymin;
+ this.ymax = ymax;
+ }
+
+ public function overlapsInY(ymin:Number, ymax:Number):Boolean
+ {
+ return !(ymax < this.ymin || ymin >= this.ymax);
+ }
+
+ public function equals(x:Number, ymin:Number, ymax:Number):Boolean
+ {
+ return x == this.x && ymin == this.ymin && ymax == this.ymax;
+ }
+}
+
+//import org.apache.flex.textLayout.utils.Twips;
+
+class Edge
+{
+ private var _xbase:Number;
+ private var _spanList:Vector.<Span>;
+
+ public function Edge()
+ {
+ _spanList = new Vector.<Span>();
+ }
+
+ public function initialize(xbase:Number):void
+ {
+ _xbase = xbase;
+ _spanList.length = 0;
+ }
+
+ public function get base():Number
+ {
+ return _xbase;
+ }
+
+ public function addSpan(x:Number, ymin:Number, ymax:Number):void
+ {
+ _spanList.push(new Span(x, ymin, ymax));
+ }
+
+ public function removeSpan(x:Number, ymin:Number, ymax:Number):void
+ {
+ for (var i:int=0; i < _spanList.length; ++i)
+ {
+ if (_spanList[i].equals(x, ymin, ymax))
+ {
+ _spanList.splice(i,1);
+ return;
+ }
+ }
+
+// CONFIG::debug { org.apache.flex.textLayout.debug.assert(false, "Deleting a span not in list"); }
+ }
+
+ public function get numSpans():int
+ {
+ return _spanList.length;
+ }
+
+ public function getMaxForSpan(ymin:Number, ymax:Number):Number
+ {
+ var res:Number = 0;
+ for each (var span:Span in _spanList)
+ {
+ if (span.x > res && span.overlapsInY(ymin, ymax))
+ res = span.x;
+ }
+ return res;
+ }
+
+ /*public function getMinForSpan(ymin:Number, ymax:Number):Number
+ {
+ var res:Number = _xbase;
+ for each (var span:Span in _spanList)
+ {
+ if (span.x < res && span.overlapsInY(ymin, ymax))
+ res = span.x;
+ }
+ return res;
+ } */
+
+ public function findNextTransition(y:Number):Number
+ {
+ var res:Number = Number.MAX_VALUE;
+ for each (var s:Span in _spanList)
+ {
+ if (s.ymin > y && s.ymin < res)
+ res = s.ymin;
+ if (s.ymax > y && s.ymax < res)
+ res = s.ymax;
+ }
+ return res;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ParcelList.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ParcelList.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ParcelList.as
new file mode 100644
index 0000000..9f2cfbb
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/ParcelList.as
@@ -0,0 +1,438 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Constants;
+ import org.apache.flex.geom.Rectangle;
+
+ import org.apache.flex.textLayout.container.ColumnState;
+ import org.apache.flex.textLayout.container.IContainerController;
+ import org.apache.flex.textLayout.container.ScrollPolicy;
+ import org.apache.flex.textLayout.debug.assert;
+ import org.apache.flex.textLayout.elements.TableCellElement;
+ import org.apache.flex.textLayout.formats.BlockProgression;
+ import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+ import org.apache.flex.textLayout.formats.LineBreak;
+
+
+
+
+ /** @private
+ * Used for composing text containers, keeps track of the areas that text in the
+ * flow is composed into.
+ *
+ * ParcelList will always have one parcel, which corresponds to the container's
+ * bounding box.
+ */
+ public class ParcelList
+ {
+ protected var _flowComposer:IFlowComposer;
+
+ /** Current vertical position in the parcel. */
+ protected var _totalDepth:Number;
+
+ /** whether the current parcel has any content */
+ protected var _hasContent:Boolean;
+
+ /** The list of parcels that are available for text layout.
+ They are appear in the array in reading order: the first text goes in the
+ first parcel, when it gets filled later text is flowed into the second
+ parcel, and so on. */
+ protected var _parcelArray:Array; /* of Parcel */
+ protected var _numParcels:int;
+ protected var _singleParcel:Parcel;
+
+ /** Index of the "current" parcel. These next two variables must be kept in sync. */
+ protected var _currentParcelIndex:int;
+ protected var _currentParcel:Parcel;
+
+ protected var _insideListItemMargin:Number;
+
+ protected var _leftMargin:Number;
+ protected var _rightMargin:Number;
+
+ protected var _explicitLineBreaks:Boolean;
+
+ /** True if text is vertical (as for some Japanese & Chinese, false otherwise */
+ protected var _verticalText:Boolean;
+
+// private static const MAX_HEIGHT:Number = 900000000; // vertical scroll max - capped to prevent loss of precision - what should it be?
+// private static const MAX_WIDTH:Number = 900000000; // horizontal scroll max - capped to prevent loss of precision - what should it be?
+
+ // a single parcellist that is checked out and checked in
+ static private var _sharedParcelList:ParcelList;
+
+ /** @private */
+ static public function getParcelList():ParcelList
+ {
+ var rslt:ParcelList = _sharedParcelList ? _sharedParcelList : new ParcelList();
+ _sharedParcelList = null;
+ return rslt;
+ }
+
+ /** @private */
+ static public function releaseParcelList(list:ParcelList):void
+ {
+ if (_sharedParcelList == null)
+ {
+ _sharedParcelList = list as ParcelList;
+ if (_sharedParcelList)
+ _sharedParcelList.releaseAnyReferences();
+ }
+ }
+
+ /** Constructor. */
+ public function ParcelList()
+ { _numParcels = 0; }
+
+ /** prevent any leaks. @private */
+ public function releaseAnyReferences():void
+ {
+ this._flowComposer = null;
+
+ _numParcels = 0;
+ _parcelArray = null;
+
+ if (_singleParcel)
+ _singleParcel.releaseAnyReferences();
+ }
+
+ CONFIG::debug public function getBounds():Array
+ {
+ var boundsArray:Array = [];
+ for (var i:int = 0; i < _numParcels; ++i)
+ boundsArray.push(getParcelAt(i));
+ return boundsArray;
+ }
+
+ public function getParcelAt(idx:int):Parcel
+ { return _numParcels <= 1 ? _singleParcel : _parcelArray[idx]; }
+
+ public function get currentParcelIndex():int
+ { return _currentParcelIndex; }
+
+ public function get explicitLineBreaks():Boolean
+ {
+ return _explicitLineBreaks;
+ }
+
+ private function get measureLogicalWidth():Boolean
+ {
+ if (_explicitLineBreaks)
+ return true;
+ if (!_currentParcel)
+ return false;
+ var controller:IContainerController = _currentParcel.controller;
+ return _verticalText ? controller.measureHeight : controller.measureWidth;
+ }
+
+ private function get measureLogicalHeight():Boolean
+ {
+ if (!_currentParcel)
+ return false;
+ var controller:IContainerController = _currentParcel.controller;
+ return _verticalText ? controller.measureWidth : controller.measureHeight;
+ }
+
+ public function get totalDepth():Number
+ {
+ return _totalDepth;
+ }
+
+ public function addTotalDepth(value:Number):Number
+ {
+ _totalDepth += value;
+ // trace("addTotalDepth", value, "newDepth", totalDepth);
+ return _totalDepth;
+ }
+
+ protected function reset():void
+ {
+ // Composition starts with an initial invalid parcel. It will start by calling next(), which will
+ // advance to the first parcel.
+ _totalDepth = 0;
+ _hasContent = false;
+
+ _currentParcelIndex = -1;
+ _currentParcel = null;
+
+ _leftMargin = 0;
+ _rightMargin = 0;
+ _insideListItemMargin = 0;
+ }
+
+ public function addParcel(column:Rectangle, controller:IContainerController, columnIndex:int):Parcel
+ {
+ var newParcel:Parcel = _numParcels == 0 && _singleParcel
+ ? _singleParcel.initialize(_verticalText, column.x,column.y,column.width,column.height,controller,columnIndex)
+ : new Parcel(_verticalText, column.x, column.y, column.width, column.height, controller, columnIndex);
+ if (_numParcels == 0)
+ _singleParcel = newParcel;
+ else if (_numParcels == 1)
+ _parcelArray = [ _singleParcel, newParcel ];
+ else
+ _parcelArray.push(newParcel);
+ _numParcels++;
+ return newParcel;
+ }
+
+ // Return numbers of parcels in this parcel list
+ public function numParcels():int
+ {
+ return this._numParcels;
+ }
+
+ // Pop up top most parcel
+ public function popParcel():Parcel
+ {
+ _numParcels -- ;
+ return _parcelArray.pop();
+ }
+
+ public function addTableCell2ColumnState(controller:IContainerController, cell:TableCellElement):void
+ {
+ var columnState:ColumnState = controller.columnState;
+ if (columnState)
+ columnState.pushTableCell(cell);
+ }
+ protected function addOneControllerToParcelList(controllerToInitialize:IContainerController):void
+ {
+ // Initialize new parcels for columns
+ var columnState:ColumnState = controllerToInitialize.columnState;
+ columnState.clearCellList();
+ for (var columnIndex:int = 0; columnIndex < columnState.columnCount; columnIndex++)
+ {
+ var column:Rectangle = columnState.getColumnAt(columnIndex);
+ if (!column.isEmpty())
+ addParcel(column, controllerToInitialize, columnIndex);
+ }
+ }
+
+ public function beginCompose(composer:IFlowComposer, controllerStartIndex:int, controllerEndIndex:int, composeToPosition:Boolean):void
+ {
+ _flowComposer = composer;
+
+ var rootFormat:ITextLayoutFormat = composer.rootElement.computedFormat;
+ _explicitLineBreaks = rootFormat.lineBreak == LineBreak.EXPLICIT;
+ _verticalText = (rootFormat.blockProgression == BlockProgression.RL);
+
+ if (composer.numControllers != 0)
+ {
+ // if controllerEndIndex is not specified then assume we are composing to position and add all controllers
+ if (controllerEndIndex < 0)
+ controllerEndIndex = composer.numControllers-1;
+ else
+ controllerEndIndex = Math.min(controllerEndIndex,composer.numControllers-1);
+ var idx:int = controllerStartIndex;
+ do
+ {
+ addOneControllerToParcelList(IContainerController(composer.getControllerAt(idx)));
+ } while (idx++ != controllerEndIndex);
+ // adjust the last container for scrolling
+ if (controllerEndIndex == composer.numControllers-1)
+ adjustForScroll(composer.getControllerAt(composer.numControllers-1), composeToPosition);
+ }
+ reset();
+ }
+
+ /** Adjust the size of the parcel corresponding to the last column of the containter, in
+ * order to account for scrolling.
+ */
+ private function adjustForScroll(containerToInitialize:IContainerController, composeToPosition:Boolean):void
+ {
+ // Expand the last parcel if scrolling could be enabled. Expand to twice what would fit in available space.
+ // We will start composing from the top, so if we've scrolled down there will be more to compose.
+ // We turn on fitAny, so that lines will be included in the container even if only a tiny portion of the line
+ // fits. This makes lines that are only partially scrolling in appear. We turn on composeToPosition if we're
+ // forcing composition to go through a given position -- this will make all lines fit, and composition will
+ // continue until it is past the supplied position.
+ var p:Parcel;
+ if (_verticalText)
+ {
+ if (containerToInitialize.horizontalScrollPolicy != ScrollPolicy.OFF)
+ {
+ p = getParcelAt(_numParcels-1);
+ if (p)
+ {
+ var horizontalPaddingAmount:Number = containerToInitialize.getTotalPaddingRight() + containerToInitialize.getTotalPaddingLeft();
+ var right:Number = p.right;
+ p.x = containerToInitialize.horizontalScrollPosition - p.width - horizontalPaddingAmount;
+ p.width = right - p.x;
+ p.fitAny = true;
+ p.composeToPosition = composeToPosition;
+ }
+ }
+ }
+ else
+ {
+ if (containerToInitialize.verticalScrollPolicy != ScrollPolicy.OFF)
+ {
+ p = getParcelAt(_numParcels-1);
+ if (p)
+ {
+ var verticalPaddingAmount:Number = containerToInitialize.getTotalPaddingBottom() + containerToInitialize.getTotalPaddingTop();
+ p.height = (containerToInitialize.verticalScrollPosition + p.height + verticalPaddingAmount) - p.y;
+ p.fitAny = true;
+ p.composeToPosition = composeToPosition;
+ }
+ }
+ }
+ }
+
+ public function get leftMargin():Number
+ {
+ return _leftMargin;
+ }
+
+ public function pushLeftMargin(leftMargin:Number):void
+ {
+ _leftMargin += leftMargin;
+ }
+
+ public function popLeftMargin(leftMargin:Number):void
+ {
+ _leftMargin -= leftMargin;
+ }
+
+ public function get rightMargin():Number
+ {
+ return _rightMargin;
+ }
+
+ public function pushRightMargin(rightMargin:Number):void
+ {
+ _rightMargin += rightMargin;
+ }
+
+ public function popRightMargin(rightMargin:Number):void
+ {
+ _rightMargin -= rightMargin;
+ }
+
+ public function pushInsideListItemMargin(margin:Number):void
+ { _insideListItemMargin += margin; }
+ public function popInsideListItemMargin(margin:Number):void
+ { _insideListItemMargin -= margin; }
+ public function get insideListItemMargin():Number
+ { return _insideListItemMargin; }
+
+ public function getComposeXCoord(o:Rectangle):Number
+ {
+ // trace("LPL: getComposeXCoord");
+ return _verticalText ? o.right : o.left;
+ }
+ public function getComposeYCoord(o:Rectangle):Number
+ {
+ // trace("LPL: getComposeYCoord");
+ return o.top;
+ }
+
+ public function getComposeWidth(o:Rectangle):Number
+ {
+ // trace("LPL: getComposeWidth");
+ if (measureLogicalWidth)
+ return Constants.MAX_LINE_WIDTH;
+ return _verticalText ? o.height : o.width;
+ }
+
+ public function getComposeHeight(o:Rectangle):Number
+ {
+ // trace("LPL: getComposeHeight");
+ if (measureLogicalHeight)
+ return Constants.MAX_LINE_WIDTH;
+ return _verticalText ? o.width : o.height;
+ }
+
+ /** Returns true if the current parcel is the last.
+ */
+ public function atLast():Boolean
+ {
+ return _numParcels == 0 || _currentParcelIndex == _numParcels -1;
+ }
+
+ public function atEnd():Boolean
+ {
+ return _numParcels == 0 || _currentParcelIndex >= _numParcels;
+ }
+
+ public function gotoParcel(index:int, depth:Number = 0):Boolean
+ {
+ if ( index < 0 || index >= _numParcels )
+ return false;
+
+ _currentParcel = this.getParcelAt(index);
+ if ( _currentParcel == null )
+ return false;
+ _currentParcelIndex = index;
+
+ _totalDepth = depth;
+
+ return true;
+ }
+
+ public function next():Boolean
+ {
+ CONFIG::debug { assert(_currentParcelIndex >= -1 && _currentParcelIndex < _numParcels, "invalid _currentParcelIndex in ParcelList"); }
+ var nextParcelIsValid:Boolean = (_currentParcelIndex + 1) < _numParcels;
+
+ _currentParcelIndex += 1;
+ _totalDepth = 0;
+
+ if (nextParcelIsValid)
+ {
+ _currentParcel = getParcelAt(_currentParcelIndex);
+ }
+ else
+ _currentParcel = null;
+
+ return nextParcelIsValid;
+ }
+
+ public function get currentParcel():Parcel
+ { return _currentParcel; }
+
+ /**Return the slug rectangle for a line that goes at the current vertical location,
+ * and could extend down for at least height pixels. Note that this function
+ * can change the current parcel, and the location within the parcel.
+ * @param slugRect result rectangle where line was fit
+ * @param height amount of contiguous vertical space that must be available
+ * @param minWidth amount of contiguous horizontal space that must be available
+ * @return true if a line slug was fit horizontal space actually available
+ */
+ public function getLineSlug(slug:Slug, height:Number, minWidth:Number, textIndent:Number, directionLTR:Boolean):Boolean
+ {
+ if (currentParcel.getLineSlug(slug, _totalDepth, height, minWidth, currentParcel.fitAny ? 1 : int(height), _leftMargin, _rightMargin, textIndent+_insideListItemMargin, directionLTR, _explicitLineBreaks))
+ {
+ if (totalDepth != slug.depth)
+ _totalDepth = slug.depth;
+ return true;
+ }
+ return false;
+ }
+
+ // Attempts to fit a float of the specified width and height in the current parcel. Float is considered to fit if it
+ // is alone on the line but exceeds the parcel width and fits within the logical height.
+ // Returns success or failure.
+ public function fitFloat(slug:Slug, totalDepth:Number, width:Number, height:Number):Boolean
+ {
+ return currentParcel.getLineSlug(slug, totalDepth, height, width, currentParcel.fitAny ? 1 : int(height), _leftMargin, _rightMargin, 0, true, _explicitLineBreaks);
+ }
+
+ } //end class
+} //end package
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SWFContext.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SWFContext.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SWFContext.as
new file mode 100644
index 0000000..f3e2e8d
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SWFContext.as
@@ -0,0 +1,85 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.compose.ISWFContext;
+
+ public class SWFContext implements ISWFContext {
+ public function callInContext(fn : Function, thisArg : Object, argArray : Array, returns : Boolean = true) : * {
+ }
+ public static function get globalSWFContext():ISWFContext
+ {
+ return GlobalSWFContext.globalSWFContext;
+ }
+ }
+}
+import org.apache.flex.textLayout.compose.ISWFContext;
+import org.apache.flex.textLayout.debug.Debugging;
+class GlobalSWFContext implements ISWFContext
+{
+ public function GlobalSWFContext()
+ { }
+
+ static public const globalSWFContext:GlobalSWFContext = new GlobalSWFContext();
+
+ public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
+ {
+ CONFIG::debug
+ {
+ var rslt:*;
+ try
+ {
+ if (returns)
+ rslt = fn.apply(thisArg, argsArray);
+
+ else
+ fn.apply(thisArg, argsArray);
+
+ if (thisArg)
+ {
+ var traceArgs:Array;
+ // later make this table driven
+ if (thisArg.hasOwnProperty("createTextLine") && fn == thisArg["createTextLine"])
+ {
+ traceArgs = [rslt,thisArg,"createTextLine"];
+ traceArgs.push.apply(traceArgs, argsArray);
+ Debugging.traceFTECall.apply(null,traceArgs);
+ }
+ else if (thisArg.hasOwnProperty("recreateTextLine") && fn == thisArg["recreateTextLine"])
+ {
+ traceArgs = [rslt,thisArg,"recreateTextLine"];
+ traceArgs.push.apply(traceArgs, argsArray);
+ Debugging.traceFTECall.apply(null,traceArgs);
+ }
+ }
+ }
+ catch(e:Error)
+ {
+ // trace(e);
+ throw(e);
+ }
+ return rslt;
+ }
+ CONFIG::release
+ {
+ if (returns)
+ return fn.apply(thisArg, argsArray);
+ fn.apply(thisArg, argsArray);
+ }
+ }
+}
\ 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/SimpleCompose.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SimpleCompose.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SimpleCompose.as
new file mode 100644
index 0000000..013532c
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/SimpleCompose.as
@@ -0,0 +1,442 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.compose.utils.NumberlineUtil;
+ import org.apache.flex.textLayout.compose.utils.TextLineUtil;
+ import org.apache.flex.text.engine.Constants;
+ import org.apache.flex.text.engine.ITextLine;
+ import org.apache.flex.textLayout.container.IContainerController;
+ import org.apache.flex.textLayout.debug.Debugging;
+ import org.apache.flex.textLayout.debug.assert;
+ import org.apache.flex.textLayout.elements.IFlowGroupElement;
+ import org.apache.flex.textLayout.elements.IFlowLeafElement;
+ import org.apache.flex.textLayout.elements.IParagraphElement;
+ import org.apache.flex.textLayout.elements.ITextFlow;
+ import org.apache.flex.textLayout.formats.BlockProgression;
+ import org.apache.flex.textLayout.formats.Direction;
+ import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+ import org.apache.flex.textLayout.formats.VerticalAlign;
+
+
+
+
+ // [ExcludeClass]
+ /** Keeps track of internal state during composition.
+ *
+ * This is the simpler version, used when there are no floats, no wraps, no columns.
+ * @private
+ */
+ public class SimpleCompose extends BaseCompose implements ISimpleCompose {
+ // reusable scratch TextFlowLine
+ protected var workingLine:ITextFlowLine = new TextFlowLine(null, null);
+
+ // resulting TextLines
+ private var _lines:Array;
+
+ // scratch aligns for VJ
+ private var _vjLines:Array;
+
+ // for figuring out when to do VJ
+ private var vjBeginLineIndex:int = 0;
+ private var vjDisableThisParcel:Boolean = false;
+ private var vjType:String;
+
+ // accumulator for absolute start computation to support truncation
+ private var _totalLength:Number;
+
+ /** Constructor. */
+ public function SimpleCompose()
+ {
+ super();
+ _lines = new Array();
+ _vjLines = new Array();
+ }
+
+ /** @private */
+ protected override function createParcelList():ParcelList
+ {
+ return ParcelList.getParcelList();
+ }
+ /** @private */
+ protected override function releaseParcelList(list:ParcelList):void
+ {
+ ParcelList.releaseParcelList(list);
+ }
+
+ protected override function initializeForComposer(composer:IFlowComposer, composeToPosition:int, controllerStartIndex:int, controllerEndIndex:int):void
+ {
+ // Always compose from the start of the flow
+ _startController = composer.getControllerAt(0);
+ _startComposePosition = 0;
+ super.initializeForComposer(composer, composeToPosition, 0, controllerEndIndex);
+
+ // vj support
+ _vjLines.splice(0);
+ vjBeginLineIndex = 0;
+ vjDisableThisParcel = false;
+ vjType =_startController.computedFormat.verticalAlign;
+ }
+
+ /** @private */
+ public override function composeTextFlow(textFlow:ITextFlow, composeToPosition:int, controllerEndIndex:int):int
+ {
+ _flowComposer = textFlow.flowComposer as IFlowComposer;
+ _curLine = workingLine;
+ CONFIG::debug { assert (_curLine != null, "_curLine is null"); }
+ // empty out lines array
+ _lines.splice(0);
+ // accumulator initialization
+ _totalLength = 0;
+
+ return super.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+ }
+
+ override protected function doVerticalAlignment(canVerticalAlign:Boolean,nextParcel:Parcel):void
+ {
+ var vjParcel:Parcel = parcelList.currentParcel;
+
+ if (canVerticalAlign && vjType != VerticalAlign.TOP && vjBeginLineIndex != _lines.length && !vjDisableThisParcel)
+ {
+ var controller:IContainerController = _curParcel.controller;
+ var beginFloatIndex:int = 0;
+ var endFloatIndex:int = 0;
+ if (controller.numFloats > 0)
+ {
+ beginFloatIndex = controller.findFloatIndexAtOrAfter(_curParcelStart);
+ endFloatIndex = controller.findFloatIndexAfter(_curElementStart + _curElementOffset);
+ }
+ applyVerticalAlignmentToColumn(vjParcel.controller,vjType,_vjLines,0,_vjLines.length, beginFloatIndex, endFloatIndex);
+ }
+
+ _vjLines.splice(0);
+ vjBeginLineIndex = _lines.length;
+ vjDisableThisParcel = false;
+ if (nextParcel)
+ vjType = nextParcel.controller.computedFormat.verticalAlign;
+ }
+
+ // all lines are visible in the factory
+ override protected function isLineVisible(textLine:ITextLine):Boolean
+ { return textLine != null; }
+
+ /** Called when we are finished composing a line. Handler for derived classes to override default behavior. */
+ override protected function endLine(textLine:ITextLine):void
+ {
+ super.endLine(textLine);
+
+ _curLine.createShape(_blockProgression, textLine);
+
+ if (textFlow.backgroundManager)
+ textFlow.backgroundManager.finalizeLine(_curLine);
+
+ textLine.userData = _totalLength; // store absolute start position in the userData field
+ _totalLength += textLine.rawTextLength; // update length accumulator
+ _lines.push(textLine);
+ if (vjType != VerticalAlign.TOP)
+ _vjLines.push(new VJHelper(textLine,_curLine.height));
+
+ commitLastLineState(_curLine);
+ }
+
+ public function get textFlow():ITextFlow
+ { return _textFlow; }
+
+ private var _resetLineHandler:Function;
+
+ /** Callback to the client to reset a line when its being rebroken */
+ public function get resetLineHandler():Function
+ { return _resetLineHandler; }
+ public function set resetLineHandler(val:Function):void
+ { _resetLineHandler = val; }
+
+ /** @private */
+ protected override function resetLine(textLine:ITextLine):void
+ {
+ super.resetLine(textLine);
+ if (_resetLineHandler != null)
+ _resetLineHandler(textLine);
+ }
+
+ /** @private */
+ protected override function composeNextLine():ITextLine
+ {
+ CONFIG::debug { assert(!_previousLine || _previousLine.validity == "valid","Bad prevline: "+Debugging.getIdentity(_previousLine)); }
+
+ var numberLine:ITextLine;
+ // create numberLine if in a listElement
+ if (_listItemElement && _listItemElement.getAbsoluteStart() == _curElementStart+_curElementOffset)
+ {
+ var isRTL:Boolean = _curParaElement.computedFormat.direction == Direction.RTL;
+ numberLine = NumberlineUtil.createNumberLine(_listItemElement, _curParaElement, _flowComposer.swfContext, isRTL ? _parcelList.rightMargin : _parcelList.leftMargin);
+ pushInsideListItemMargins(numberLine);
+ }
+
+ // space to palce a line?
+ if (!_parcelList.getLineSlug(_lineSlug, 0, 0, _textIndent, _curParaFormat.direction == Direction.LTR))
+ return null;
+
+ var textLine:ITextLine;
+
+ for (;;)
+ {
+ for (;;)
+ {
+ // generate new line
+ CONFIG::debug { assert(!_parcelList.atEnd(), "failing to stop"); }
+ CONFIG::debug { assert(_curElement is IFlowLeafElement, "element must be leaf before calling composeLine"); }
+
+ textLine = createTextLine(_lineSlug.width, !_lineSlug.wrapsKnockOut /* don't allow emergency breaks next to floats or padded elements */);
+ if (textLine)
+ break;
+
+ // force advance within the parcel to the next wider slug, or (if there are no more) to the next parcel
+ var newDepth:Number = _curParcel.findNextTransition(_lineSlug.depth);
+ if (newDepth < Number.MAX_VALUE)
+ {
+ _parcelList.addTotalDepth(newDepth - _lineSlug.depth);
+ _parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR);
+ }
+ else
+ {
+ advanceToNextParcel();
+ if (!_parcelList.atEnd())
+ if (_parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR))
+ continue;
+ popInsideListItemMargins(numberLine);
+ return null;
+ }
+ }
+
+
+ // updates _lineSlug
+ if (fitLineToParcel(textLine, true, numberLine)) // TODO!!!!!!
+ break; // we have a good line
+ if (resetLineHandler != null)
+ resetLineHandler(textLine);
+ if (_parcelList.atEnd()) // keep going
+ {
+ popInsideListItemMargins(numberLine);
+ return null;
+ }
+ }
+
+ popInsideListItemMargins(numberLine);
+
+ CONFIG::debug { assert(textLine != null, "textLine != null"); }
+ return textLine;
+ }
+
+ /** @private */
+ public function swapLines(lines:Array):Array
+ {
+ var current:Array = _lines;
+ _lines = lines;
+ return current;
+ }
+
+ /** Final adjustment on the content bounds. */
+ override protected function finalParcelAdjustment(controller:IContainerController):void
+ {
+ CONFIG::debug { assert(controller.absoluteStart == 0,"SimpleCompose: multiple controllers not supported"); }
+
+ var minX:Number = Constants.MAX_LINE_WIDTH;
+ var minY:Number = Constants.MAX_LINE_WIDTH;
+ var maxX:Number = -Constants.MAX_LINE_WIDTH;
+
+ var verticalText:Boolean = _blockProgression == BlockProgression.RL;
+
+ if (!isNaN(_parcelLogicalTop))
+ {
+ if (verticalText)
+ maxX = _parcelLogicalTop;
+ else
+ minY = _parcelLogicalTop;
+ }
+
+ if (!_measuring)
+ {
+ if (verticalText)
+ minY = _accumulatedMinimumStart;
+ else
+ minX = _accumulatedMinimumStart;
+ }
+ else
+ {
+ var textLine:ITextLine;
+ var startPos:int = 0;
+
+ var firstLineAdjust:Number;
+ var effectiveIndent:Number;
+ var edgeAdjust:Number;
+ var curPara:IParagraphElement;
+ var curParaFormat:ITextLayoutFormat;
+ var paddingVerticalAdjust:Number = 0; // logical vertical adjustment due to padding on paragraph & divs
+ var paddingHorizontalAdjust:Number = 0; // logical horizontal adjustment due to padding on paragraph & divs
+ var previousParagraph:IParagraphElement = null;
+
+ for each (textLine in _lines)
+ {
+ var leaf:IFlowLeafElement = controller.textFlow.findLeaf(startPos);
+ var para:IParagraphElement = leaf.getParagraph();
+ if (para != previousParagraph)
+ {
+ // Recalculate padding values for the new paragraph
+ paddingVerticalAdjust = 0;
+ paddingHorizontalAdjust = 0;
+ var fge:IFlowGroupElement = para;
+ while (fge && fge.parent)
+ {
+ if (verticalText)
+ {
+ paddingVerticalAdjust += (fge.getEffectivePaddingRight() + fge.getEffectiveBorderRightWidth() + fge.getEffectiveMarginRight());
+ paddingHorizontalAdjust += (fge.getEffectivePaddingTop() + fge.getEffectiveBorderTopWidth() + fge.getEffectiveMarginTop());
+ }
+ else
+ {
+ paddingVerticalAdjust += (fge.getEffectivePaddingTop() + fge.getEffectiveBorderTopWidth() + fge.getEffectiveMarginTop());
+ paddingHorizontalAdjust += (fge.getEffectivePaddingLeft() + fge.getEffectiveBorderLeftWidth() + fge.getEffectiveMarginLeft());
+ }
+ fge = fge.parent;
+ }
+ previousParagraph = para;
+ }
+
+ // Check the logical vertical dimension first
+ // If the lines have children, they may be inlines. The origin of the ITextLine is the baseline,
+ // which does not include the ascent of the inlines or the text. So we have to factor that in.
+ // var verticalAdjust:Number = verticalText ? textLine.descent : textLine.ascent;
+ var inlineAscent:Number = 0;
+ if (textLine.numElements > 0) // adjustjust logical vertical coord to take into account inlines
+ {
+ var leafStart:int = leaf.getAbsoluteStart();
+ inlineAscent = TextLineUtil.getTextLineTypographicAscent(textLine, leaf, leafStart, startPos + textLine.rawTextLength);
+ }
+
+ // Figure out the logical horizontal adjustment
+ CONFIG::debug { assert(curPara != para, "found it"); }
+ if (curPara != para)
+ {
+ curParaFormat = para.computedFormat;
+ if (curParaFormat.direction == Direction.LTR)
+ {
+ firstLineAdjust = Math.max(curParaFormat.textIndent, 0);
+ effectiveIndent = curParaFormat.paragraphStartIndent;
+ }
+ else
+ {
+ firstLineAdjust = 0;
+ effectiveIndent = curParaFormat.paragraphEndIndent;
+ }
+ }
+ effectiveIndent += paddingHorizontalAdjust;
+
+ edgeAdjust = textLine.textBlockBeginIndex == 0 ? effectiveIndent + firstLineAdjust : effectiveIndent;
+ edgeAdjust = verticalText ? textLine.y - edgeAdjust : textLine.x - edgeAdjust;
+
+ var numberLine:ITextLine = TextLineUtil.findNumberLine(textLine);
+
+ if (numberLine)
+ {
+ var numberLineStart:Number = verticalText ? numberLine.y+textLine.y : numberLine.x+textLine.x;
+ edgeAdjust = Math.min(edgeAdjust,numberLineStart);
+ }
+
+ if (verticalText)
+ {
+ minY = Math.min(edgeAdjust, minY);
+ maxX = Math.max(textLine.x + Math.max(inlineAscent,textLine.ascent) + paddingVerticalAdjust, maxX);
+ }
+ else
+ {
+ minX = Math.min(edgeAdjust, minX);
+ if (inlineAscent < textLine.ascent)
+ inlineAscent = textLine.ascent;
+ minY = Math.min(textLine.y - (inlineAscent + paddingVerticalAdjust), minY);
+ }
+ startPos += textLine.rawTextLength;
+ }
+ }
+
+ // Don't make adjustments for tiny fractional values.
+ /*if (minX != _parcelLeft && Math.abs(minX-_parcelLeft) >= 1)
+ _parcelLeft = minX;
+ if (maxX != _parcelRight && Math.abs(maxX-_parcelRight) >= 1)
+ _parcelRight = maxX;
+ if (minY != _parcelTop && Math.abs(minY-_parcelTop) >= 1)
+ _parcelTop = minY;*/
+ if (minX != Constants.MAX_LINE_WIDTH && Math.abs(minX-_parcelLeft) >= 1)
+ _parcelLeft = minX;
+ if (maxX != -Constants.MAX_LINE_WIDTH && Math.abs(maxX-_parcelRight) >= 1)
+ _parcelRight = maxX;
+ if (minY != Constants.MAX_LINE_WIDTH && Math.abs(minY-_parcelTop) >= 1)
+ _parcelTop = minY;
+
+ }
+
+ public override function releaseAnyReferences():void
+ {
+ super.releaseAnyReferences();
+ workingLine.initialize(null,0,0,0,0,null);
+ resetLineHandler = null;
+ // parcelList.releaseAnyReferences();
+ }
+
+ public function get lines():Array
+ {
+ return _lines;
+ }
+ }
+}
+import org.apache.flex.text.engine.ITextLine;
+import org.apache.flex.textLayout.compose.IVerticalJustificationLine;
+
+class VJHelper implements IVerticalJustificationLine
+{
+ private var _line:ITextLine;
+ private var _height:Number;
+
+ public function VJHelper(line:ITextLine,h:Number)
+ {
+ _line = line;
+ _height = h;
+ }
+ public function get x():Number
+ { return _line.x; }
+ public function set x(val:Number):void
+ { _line.x = val; }
+
+ public function get y():Number
+ { return _line.y; }
+ public function set y(val:Number):void
+ { _line.y = val; }
+
+ public function get ascent():Number
+ { return _line.ascent; }
+ public function get descent():Number
+ { return _line.descent; }
+ public function get height():Number
+ {
+ return _height;
+ }
+
+ public function set height(value:Number):void
+ {
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Slug.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Slug.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Slug.as
new file mode 100644
index 0000000..7fd0788
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/compose/Slug.as
@@ -0,0 +1,32 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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
+{
+ /** A Slug is geomtrical line information, generated by a Parcel. It has data required for composition. */
+ // [ExcludeClass]
+ public class Slug
+ {
+ public var leftMargin:Number;
+ public var rightMargin:Number;
+ public var width:Number; // logical width
+ public var depth:Number;
+ public var height:Number; // logical height
+ public var wrapsKnockOut:Boolean; // true if the slug is narrow because it encountered a knockout (e.g., for a float)
+ }
+}