blob: 3441a577ebb11a0ea267a8d16342ffdce87b664c [file] [log] [blame]
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<mx:Canvas
creationComplete="handleCreationComplete()"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flow="library://ns.adobe.com/flashx/textLayout">
<mx:Script>
<![CDATA[
import flash.text.engine.ElementFormat;
import flash.text.engine.FontDescription;
import flash.text.engine.LineJustification;
import flash.text.engine.SpaceJustifier;
import flash.text.engine.TextBlock;
import flash.text.engine.TextElement;
import flash.text.engine.TextLine;
import flash.text.engine.TextLineValidity;
import flashx.textLayout.TextLayoutVersion;
import flashx.textLayout.compose.StandardFlowComposer;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.container.TextContainerManager;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.elements.Configuration;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.SpanElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.factory.StringTextLineFactory;
import flashx.textLayout.factory.TextFlowTextLineFactory;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.tlf_internal;
import mx.collections.ArrayCollection;
import mx.controls.Text;
use namespace tlf_internal;
private static var stringFactory:StringTextLineFactory = new StringTextLineFactory();
private static var textFlowFactory:TextFlowTextLineFactory = new TextFlowTextLineFactory();
// data for the current run
private var numberOfFields:int = 0;
private var numberOfIterations:int = 0;
private var beginCreationTime:int;
private var endCreationTime:int;
private var beginRenderTime:int;
// state for running tests
private var currIteration:int = -1;
private var beginThisRender:int;
private var timingRendering:Boolean = false;
// timers
private var beginTestTime:int;
public var totalCreationTime:int;
public var totalRenderTime:int;
private var resultText:Text;
private var _func:String;
static private const testTypeArray:ArrayCollection = new ArrayCollection([
{label:"TextField", data:"buildTextFieldExample"},
{label:"EditableTextField", data:"buildEditableTextFieldExample"},
{label:"FTE", data:"buildFTEExampleFactory"},
{label:"Vellum Factory", data:"buildVellumExampleFactoryCallback"},
{label:"Vellum Factory2", data:"buildVellumExampleFactoryCallback2"},
{label:"Vellum TextFlow", data:"buildVellumExampleTextFlow"},
{label:"Vellum TextFlowEdit", data:"buildVellumExampleTextFlowEdit"},
{label:"Vellum TextFlowImport", data:"buildVellumExampleTextFlowImport"},
{label:"Vellum TextContainerManager", data:"buildVellumExampleInputManager"},
{label:"Vellum TCM HostFormat", data:"buildVellumExampleInputManagerHostFormat"},
// {label:"Vellum Measure", data:"buildVellumExampleMeasureFactoryCallback"},
{label:"Rectangles", data:"buildRectangles"},
{label:"Nothing", data:"buildNothing"}
]);
private function setDebugFlag():void
{
var e:Error = new Error();
var s:String = e.getStackTrace();
// trace(s);
var i:int = s.indexOf("setDebugFlag");
if (s.charAt(i + 14) == '[')
debugMode = true;
}
[Bindable]
public var debugMode:Boolean = false;
public function handleCreationComplete(): void
{
setDebugFlag();
// runTheTest();
return;
}
// sizes for item placement
public var textWidth:Number = 30;
public var textHeight:Number = 12;
public function runTheTest():void
{
// clear the previous run
if (resultText)
{
lineHolder.removeChild(resultText);
resultText = null;
}
numberOfFields = int(numberFieldsInput.text);
numberOfIterations = int(numberIterationsInput.text);
_func = testTypeArray[testTypeCombo.selectedIndex].data;
currIteration = 0;
addEventListener(Event.ENTER_FRAME,handleEnterFrame);
runButton.enabled = false;
totalCreationTime = 0;
totalRenderTime = 0;
beginTestTime = getTimer();
}
public function createOneStep():void
{
while (lineHolder.rawChildren.numChildren)
lineHolder.rawChildren.removeChildAt(0);
var begTime:int = getTimer();
var funcCall:Function = this[_func];
const xInit:Number = 10;
const yInit:Number = 10;
const xDelta:Number = 90;
const yDelta:Number = 15;
var xpos:Number = xInit;
var ypos:Number = yInit;
for (var testNum:int = 0; testNum < numberOfFields; testNum++)
{
var example:DisplayObject = funcCall();
if (example)
{
example.x = xpos;
example.y = ypos;
lineHolder.rawChildren.addChild(example);
xpos += xDelta;
if (xpos + xDelta > this.width)
{
xpos = xInit;
ypos += yDelta;
if (ypos + 2*yDelta > (this.height-controlBox.height))
ypos = yInit;
}
}
}
totalCreationTime += getTimer()-begTime;
}
/** build FTE data each time */
public function buildFTEExample():DisplayObject
{
var elementFormat:ElementFormat = new ElementFormat();
var textElement:TextElement = new TextElement(testData.text, elementFormat)
var textBlock:TextBlock = new TextBlock(textElement);
var textLine:TextLine = textBlock.createTextLine();
var sprite:Sprite = new Sprite();
sprite.addChild(textLine);
return sprite;
}
static private var templateTextElement:TextElement = null;
static private var templateTextBlock:TextBlock = null;
/** FTE as a factory */
public function buildFTEExampleFactory():DisplayObject
{
if (!templateTextElement)
{
var elementFormat:ElementFormat = new ElementFormat();
var fontDescription:FontDescription = new FontDescription();
fontDescription.fontName = "Times New Roman";
elementFormat.fontDescription = fontDescription;
templateTextElement = new TextElement();
templateTextElement.elementFormat = elementFormat;
templateTextBlock = new TextBlock(templateTextElement);
templateTextBlock.textJustifier = new SpaceJustifier("en",LineJustification.UNJUSTIFIED,false);
}
templateTextElement.text = testData.text;
var textLine:TextLine = templateTextBlock.createTextLine();
textLine.validity = TextLineValidity.STATIC;
return textLine;
}
/** full vellum instantiation with a SpritTextContainer */
public function buildVellumExample():DisplayObject
{
var textFlow:TextFlow = new TextFlow();
var para:ParagraphElement = new ParagraphElement();
var span:SpanElement = new SpanElement();
span.text = testData.text;
para.replaceChildren(0, 0, span);
textFlow.replaceChildren(0, 0, para);
var textContainer:Sprite = new Sprite();
var sdc:StandardFlowComposer = new StandardFlowComposer();
//sdc.setRootElement(this);
//sdc.rootElement;
var controller:ContainerController = new ContainerController(textContainer);
sdc.addController(controller);
textFlow.flowComposer = sdc;
controller.setCompositionSize(300, 100);
textFlow.flowComposer.updateAllControllers();
// trace("added container (", textContainer.x, ",", textContainer.y, ")", textContainer.numChildren, "children");
// trace(displayHierarchy(textContainer));
return textContainer;
}
static private var _bounds:Rectangle = new Rectangle(0,0,300,100);
static private var _textLine:TextLine;
static public function callback(tl:TextLine):void
{
if (_textLine == null)
_textLine = tl;
else
_textLine.addChild(tl);
}
/** use the vellum factory via the callback */
public function buildVellumExampleFactoryCallback():DisplayObject
{
_textLine = null;
stringFactory.text = testData.text;
stringFactory.compositionBounds = _bounds;
stringFactory.createTextLines(callback);
return _textLine;
}
 /** use the vellum factory via the callback */
public function buildVellumExampleInputManager():DisplayObject
{
var s:Sprite = new Sprite();
// var manager:TextContainerManager = new TextContainerManager(s,_bounds);
var manager:TextContainerManager = new TextContainerManager(s,null); // TODO!!!
manager.compositionWidth = _bounds.width;
manager.compositionHeight = _bounds.height;
manager.setText(testData.text);
manager.updateContainer();
s.x = _bounds.x;
s.y = _bounds.y;
return s;
}
private static function getRandomInteger(start:int, end:int):int
// Return a random number between start and end
{
var num:Number = Math.random();
return Math.ceil((num * (end - start)) + start);
}
/** use the vellum factory via the callback */
public function buildVellumExampleInputManagerHostFormat():DisplayObject
{
var s:Sprite = new Sprite();
// var manager:TextContainerManager = new TextContainerManager(s,_bounds);
var manager:TextContainerManager = new TextContainerManager(s,null); // TODO!!!
manager.compositionWidth = _bounds.width;
manager.compositionHeight = _bounds.height;
manager.setText(testData.text);
var hostFormat:TextLayoutFormat = new TextLayoutFormat(TextLayoutFormat.defaultFormat);
hostFormat.color = getRandomInteger(0,0xFFFFFF);
manager.hostFormat = hostFormat;
// force to a full TextFlow
manager.beginInteraction();
manager.endInteraction();
manager.updateContainer();
s.x = _bounds.x;
s.y = _bounds.y;
return s;
}
/** use the vellum factory via the callback */
private var myFactory:StringTextLineFactory = new StringTextLineFactory();
public function buildVellumExampleFactoryCallback2():DisplayObject
{
_textLine = null;
stringFactory.text = testData.text;
stringFactory.compositionBounds = _bounds;
stringFactory.createTextLines(callback);
return _textLine;
}
/** use the vellum factory via the callback */
static private var _mBounds:Rectangle = new Rectangle(0,0,0,0);
public function buildVellumExampleMeasureFactoryCallback():DisplayObject
{
_textLine = null;
_mBounds.width = NaN;
_mBounds.height = NaN;
myFactory.text = testData.text;
myFactory.compositionBounds = _mBounds;
myFactory.createTextLines(callback);
_mBounds = myFactory.getContentBounds();
trace("measure",_mBounds.width,_mBounds.height);
return _textLine;
}
static private var _tf:TextFlow;
/** this example generates TextLines from a single unmodified TextFlow */
public function buildVellumExampleFactoryFromTextFlowCallback():DisplayObject
{
if (_tf == null)
{
_tf = new TextFlow();
var p:ParagraphElement = new ParagraphElement();
_tf.replaceChildren(0,0,p);
var s:SpanElement = new SpanElement();
p.replaceChildren(0,0,s);
s.text = testData.text;
}
_textLine = null;
textFlowFactory.compositionBounds = _bounds;
textFlowFactory.createTextLines(callback,_tf);
return _textLine;
}
public function buildVellumExampleTextFlowEdit():DisplayObject
{
return buildVellumExampleTextFlow(new EditManager());
}
public function buildVellumExampleTextFlow(im:EditManager = null):DisplayObject
{
var tf:TextFlow = new TextFlow();
var p:ParagraphElement = new ParagraphElement();
tf.addChild(p);
var s:SpanElement = new SpanElement();
p.addChild(s);
s.text = testData.text;
tf.interactionManager = im;
var rslt:Sprite = new Sprite();
tf.flowComposer.addController(new ContainerController(rslt,_bounds.width,_bounds.height));
tf.flowComposer.updateAllControllers();
return rslt;
}
public function buildVellumExampleTextFlowImport():DisplayObject
{
var markup:XML = <TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p><span>{testData.text}</span></p></TextFlow>;
var tf:TextFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT);
var rslt:Sprite = new Sprite();
tf.flowComposer.addController(new ContainerController(rslt,_bounds.width,_bounds.height));
tf.flowComposer.updateAllControllers();
return rslt;
}
/** build rectangles */
public function buildRectangles():DisplayObject
{
var s:Shape = new Shape();
s.graphics.beginFill(0xff0000); // red
s.graphics.drawRect(0,0,textWidth/2,textHeight/2);
s.graphics.endFill();
return s;
}
/** build a TextField */
static private var defaultTextFormat:TextFormat;
public function buildTextFieldExample():DisplayObject
{
if (!defaultTextFormat)
{
defaultTextFormat = new TextFormat();
defaultTextFormat.font = "Times New Roman";
}
var a:TextField = new TextField();
a.defaultTextFormat = defaultTextFormat;
a.text = testData.text;
a.width = 300;
a.height = 100;
return a;
}
/** build an editable TextField */
public function buildEditableTextFieldExample():DisplayObject
{
if (!defaultTextFormat)
{
defaultTextFormat = new TextFormat();
defaultTextFormat.font = "Times New Roman";
}
var a:TextField = new TextField();
a.type = TextFieldType.INPUT;
a.defaultTextFormat = defaultTextFormat;
a.text = testData.text;
a.width = 300;
a.height = 100;
return a;
}
/** test that builds nothing - used to measure the overhead of the harness */
public function buildNothing():DisplayObject
{ return null; }
// debugging code
private function displayHierarchy(root:DisplayObject):String
{
var outputString:String;
outputString = flash.utils.getQualifiedClassName(root);
outputString += " rect (" + root.x.toString() + "," + root.y.toString() + "," + root.width.toString() + "," + root.height.toString() + ")";
if (root is DisplayObjectContainer && (root as DisplayObjectContainer).numChildren > 0)
{
outputString += " {\n";
for (var i:int = 0; i < (root as DisplayObjectContainer).numChildren; i++)
outputString += displayHierarchy((root as DisplayObjectContainer).getChildAt(i));
outputString += "}\n";
}
return outputString;
}
/** generate a report at the next enter frame */
public function handleEnterFrame(e:Event): void
{
if (currIteration == -1)
return;
if (timingRendering)
{
totalRenderTime += getTimer()-beginThisRender;
timingRendering = false;
}
if (currIteration == numberOfIterations)
{
var totalTestTime:int = getTimer()-beginTestTime;
flash.system.System.gc(); //mark
flash.system.System.gc(); //sweep
var memoryAllocated:Number = flash.system.System.totalMemory/1024;
trace(_func,"creation time (msecs)",totalCreationTime.toString(), "render time (msecs)",totalRenderTime.toString(), "total time (msecs)",totalTestTime.toString(), " mem (K)", memoryAllocated);
var testDescription:String = "fields: " + numberOfFields.toString() + " iters: " + numberOfIterations.toString() + " data: " + testData.text;
var playerType:String = this.debugMode ? "DEBUGGING PLAYER (not suitable for measuring performance)" : "RELEASE PLAYER "+Capabilities.version;
var vellumType:String = "Vellum build: " + flashx.textLayout.TextLayoutVersion.BUILD_NUMBER + "\n" + (Configuration.tlf_internal::debugCodeEnabled ? "DEBUG vellum engine (not suitable for measuring performance)" : "RELEASE vellum engine");
resultText = new Text();
resultText.text = _func + "\n" + testDescription + "\nCreationTime (msecs): " + totalCreationTime.toString() + "\nRenderTime (msec): " + totalRenderTime.toString() + "\nTotalTime (msec): " + totalTestTime.toString()
+ " \nmem (K): " + memoryAllocated.toString() + "\n" + playerType + "\n" + vellumType;
resultText.x = 100;
resultText.y = 140;
resultText.width = 400;
resultText.setStyle("fontFamily", "Minion Pro");
resultText.setStyle("fontSize", 24);
resultText.opaqueBackground = 0xFFFFFFFF;
lineHolder.addChild(resultText);
this.dispatchEvent(new Event(Event.COMPLETE));
currIteration = -1;
runButton.enabled = true;
removeEventListener(Event.ENTER_FRAME,handleEnterFrame);
}
else
{
createOneStep();
currIteration++;
timingRendering = true;
beginThisRender = getTimer();
}
}
]]>
</mx:Script>
<mx:VBox>
<mx:HBox id="controlBox" paddingLeft="4" paddingTop="4">
<mx:Label text="VellumWordTest" fontWeight="bold"/>
<mx:ComboBox id="testTypeCombo" editable="false" closeDuration="0" openDuration="0" selectionDuration="0"
paddingLeft="4" paddingTop="4" selectedIndex="0"
dataProvider="{testTypeArray}"/>
<mx:Label text="NumberFields:" fontWeight="bold"/>
<mx:TextInput id="numberFieldsInput" text="4000" width="60"/>
<mx:Label text="NumberIterations:" fontWeight="bold"/>
<mx:TextInput id="numberIterationsInput" text="1" width="60"/>
<mx:Label text="TestData:" fontWeight="bold"/>
<mx:TextInput id="testData" text="Hello world" width="120"/>
<mx:Button id="runButton" label="Run" click="runTheTest()"/>
</mx:HBox>
<mx:Canvas id="lineHolder"/>
</mx:VBox>
</mx:Canvas>