blob: 559f70f523517bef1e0d9fc38c78e826908c2587 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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 UnitTest.Tests
{
import UnitTest.ExtendedClasses.TestSuiteExtended;
import UnitTest.ExtendedClasses.VellumTestCase;
import UnitTest.Fixtures.TestConfig;
import UnitTest.Validation.MD5;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.IBitmapDrawable;
import flash.display.Sprite;
import flash.events.*;
import flash.filters.BitmapFilter;
import flash.filters.BitmapFilterQuality;
import flash.filters.BlurFilter;
import flash.geom.Rectangle;
import flash.system.*;
import flash.text.engine.*;
import flash.utils.ByteArray;
import flashx.textLayout.*;
import flashx.textLayout.compose.StandardFlowComposer;
import flashx.textLayout.compose.TextLineRecycler;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.container.ScrollPolicy;
import flashx.textLayout.container.TextContainerManager;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.edit.ISelectionManager;
import flashx.textLayout.edit.SelectionManager;
import flashx.textLayout.elements.*;
import flashx.textLayout.events.StatusChangeEvent;
import flashx.textLayout.events.UpdateCompleteEvent;
import flashx.textLayout.factory.StringTextLineFactory;
import flashx.textLayout.factory.TextFlowTextLineFactory;
import flashx.textLayout.formats.TextLayoutFormat;
import mx.containers.Canvas;
import mx.core.ByteArrayAsset;
import mx.utils.LoaderUtil;
use namespace tlf_internal;
public class TextLineFilterTest extends VellumTestCase
{
private var displayobject:DisplayObject;
private var TestCanvas:Canvas = null;
private var ItemsToRemove:Array;
private var text:String = 'There are many such lime-kilns in that tract of country. ';
private var headingFlow:TextFlow;
private var bodyFlow:TextFlow;
private var headController:CustomContainerController;
private var bodyController:CustomContainerController;
private const bodyMarkup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008' fontSize='18' " +
"textIndent='10' paragraphSpaceBefore='6' paddingTop='8' paddingBottom='8' paddingLeft='8' paddingRight='8'>" +
"<flow:p paragraphSpaceBefore='inherit' >" +
"<flow:span>There are many </flow:span>" +
"<flow:span fontStyle='italic'>such</flow:span>" +
"<flow:span> lime-kilns in that tract of country, for the purpose of burning the white" +
" marble which composes a large part of the substance of the hills. Some of them, built " +
"years ago, and long deserted, with weeds growing in the vacant round of the interior, " +
"which is open to the sky, and grass and wild-flowers rooting themselves into the chinks " +
"of the stones, look already like relics of antiquity, and may yet be overspread with the" +
" lichens of centuries to come. Others, where the lime-burner still feeds his daily and " +
"nightlong fire, afford points of interest to the wanderer among the hills, who seats " +
"himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. " +
"It is a lonesome, and, when the character is inclined to thought, may be an intensely " +
"thoughtful occupation; as it proved in the case of Ethan Brand, who had mused to such " +
"strange purpose, in days gone by, while the fire in this very kiln was burning.</flow:span>" +
"</flow:p>" +
"<flow:p paragraphSpaceBefore='inherit'>" +
"<flow:span>" +
"The man who now watched the fire was of a different order, and troubled himself with no " +
"thoughts save the very few that were requisite to his business. At frequent intervals, " +
"he flung back the clashing weight of the iron door, and, turning his face from the " +
"insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a " +
"long pole. Within the furnace were seen the curling and riotous flames, and the burning " +
"marble, almost molten with the intensity of heat; while without, the reflection of the " +
"fire quivered on the dark intricacy of the surrounding forest, and showed in the " +
"foreground a bright and ruddy little picture of the hut, the spring beside its door, the " +
"athletic and coal-begrimed figure of the lime-burner, and the halffrightened child, " +
"shrinking into the protection of his father's shadow. And when again the iron door was " +
"closed, then reappeared the tender light of the half-full moon, which vainly strove to " +
"trace out the indistinct shapes of the neighboring mountains; and, in the upper sky, " +
"there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, " +
"though thus far down into the valley the sunshine had vanished long and long ago.</flow:span>" +
"</flow:p>" +
"</flow:TextFlow>";
// embed alice - this simplifies things - don't need to trust the swf and pass the xml around with it
[Embed(source="../../../../test/testFiles/markup/tlf/alice.xml",mimeType="application/octet-stream")]
private var AliceClass : Class;
public function TextLineFilterTest(methodName:String, testID:String, testConfig:TestConfig, testCaseXML:XML=null)
{
ItemsToRemove = new Array();
super(methodName, testID, testConfig, testCaseXML);
//reset containerType and ID
containerType = "custom";
// Note: These must correspond to a Watson product area (case-sensitive)
metaData.productArea = "Text Container";
}
public static function suiteFromXML(testListXML:XML, testConfig:TestConfig, ts:TestSuiteExtended):void
{
var testCaseClass:Class = TextLineFilterTest;
VellumTestCase.suiteFromXML(testCaseClass, testListXML, testConfig, ts);
}
override public function setUp() : void
{
cleanUpTestApp();
TestDisplayObject = testApp.getDisplayObject();
if (TestDisplayObject)
{
TestCanvas = Canvas(TestDisplayObject);
}
else
{
fail ("Did not get a blank canvas to work with");
}
}
private var bodyContainer:Sprite;
public function initApp():void
{
// create body text flow, import body text, and assign flow composer
bodyFlow = new TextFlow();
bodyFlow = TextConverter.importToFlow(bodyMarkup, TextConverter.TEXT_LAYOUT_FORMAT);
bodyFlow.flowComposer = new StandardFlowComposer();
bodyContainer = new Sprite();
bodyController = new CustomContainerController(bodyContainer, 800, 1000);
bodyController.updateCompositionShapes();
//bodyController.addTextLine(tl1, 0);
bodyContainer.x = 20;
bodyContainer.y = 20;
// create container format to specify columns
var bodyContainerFormat:TextLayoutFormat = new TextLayoutFormat();
bodyContainerFormat.columnWidth = 390;
bodyContainerFormat.columnGap = 15;
bodyController.format = bodyContainerFormat;
// enable scrolling
bodyController.verticalScrollPolicy = ScrollPolicy.AUTO;
}
/**
* Apply a filter to the text lines and the selection
*/
public function textlineAndSelectionFilterTest():void
{
initApp();
bodyFlow.interactionManager = new SelectionManager();
var selectManager:ISelectionManager = bodyFlow.interactionManager;
selectManager.selectRange(0, 107);
selectManager.refreshSelection();
// add controller, add container to stage, and display body text
bodyFlow.flowComposer.addController(bodyController);
bodyFlow.flowComposer.updateAllControllers();
TestCanvas.rawChildren.addChild(DisplayObject(bodyContainer));
ItemsToRemove.push(bodyContainer);
System.gc(); //mark
System.gc(); //sweep
}
public function getBitmapFilter():BitmapFilter {
var blurX:Number = 3;
var blurY:Number = 3;
return new BlurFilter(blurX, blurY, BitmapFilterQuality.HIGH);
}
/**
* Apply a filter to the text lines, but not the selection
*/
public function textlinesFilterTest():void
{
initApp();
bodyFlow.interactionManager = new SelectionManager();
var selectManager:ISelectionManager = bodyFlow.interactionManager;
// add controller, add container to stage, and display body text
bodyFlow.flowComposer.addController(bodyController);
bodyFlow.flowComposer.updateAllControllers();
TestCanvas.rawChildren.addChild(DisplayObject(bodyContainer));
ItemsToRemove.push(bodyContainer);
System.gc(); //mark
System.gc(); //sweep
}
/**
* Apply a filter to the selection, but not the textline
*/
public function selectionFilterTest():void
{
initApp();
bodyFlow.interactionManager = new SelectionManager();
var selectManager:ISelectionManager = bodyFlow.interactionManager;
selectManager.selectRange(1000, 2000);
selectManager.refreshSelection();
// add controller, add container to stage, and display body text
bodyFlow.flowComposer.addController(bodyController);
bodyFlow.flowComposer.updateAllControllers();
TestCanvas.rawChildren.addChild(DisplayObject(bodyContainer));
ItemsToRemove.push(bodyContainer);
System.gc(); //mark
System.gc(); //sweep
}
private var recycledTextLine:TextLine;
private var composedTextLine:TextLine;
private var _lines:Array;
private var textLine_invalid:TextLine;
private static function createInvalidTextLine():TextLine
{
var elementFormat:ElementFormat = new ElementFormat();
var textElement:TextElement = new TextElement("aaa", elementFormat)
var textBlock:TextBlock = new TextBlock(textElement);
var textLine:TextLine = textBlock.createTextLine();
textLine.validity = TextLineValidity.INVALID;
return textLine;
}
public function recycleLineByFlowComposer():void
{
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
//create a TextFlow
var textFlow:TextFlow = new TextFlow();
textFlow.mxmlChildren = [ "Hello, World" ];
var textContainer:Sprite = new Sprite();
var textController:ContainerController = new CustomContainerController(textContainer, 800, 1000);
textFlow.flowComposer.addController(textController);
//compose a single line which should be from recycler
textFlow.flowComposer.updateAllControllers();
TestCanvas.rawChildren.addChild(DisplayObject(textContainer));
//check if the composed line is same as the recycled one
composedTextLine = textFlow.flowComposer.getLineAt(0).getTextLine();
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine);
}
public function recycleLineByFlowFactory():void
{
_lines = new Array();
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
var factory:TextFlowTextLineFactory = new TextFlowTextLineFactory();
factory.compositionBounds = new Rectangle( 100, 100, 200, 130 );
var flow:TextFlow = new TextFlow();
var span:SpanElement = new SpanElement();
span.text = "Hello World.";
var para:ParagraphElement = new ParagraphElement();
para.addChild( span );
flow.addChild( para );
//compose a single line which should be from recycler
factory.createTextLines(useTextLines, flow );
//check if the composed line is same as the recycled one
composedTextLine = _lines[0];
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine);
}
public function recycleLineByStringFactory():void
{
_lines = new Array();
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
var factory:StringTextLineFactory = new StringTextLineFactory();
factory.compositionBounds = new Rectangle( 100, 100, 200, 130 );
factory.text = "Hello World";
//compose a single line which should be from recycler
factory.createTextLines(useTextLines);
//check if the composed line is same as the recycled one
composedTextLine = _lines[0];
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine);
}
public function stringFactoryBackgroundColor():void
{
_lines = new Array();
var factory:StringTextLineFactory = new StringTextLineFactory();
factory.compositionBounds = new Rectangle( 100, 100, 200, 130 );
factory.text = "Hello World";
factory.textFlowFormat = TextLayoutFormat.createTextLayoutFormat({blockProgression:writingDirection[0],direction:writingDirection[1]});
factory.spanFormat = TextLayoutFormat.createTextLayoutFormat({backgroundColor:0xffff4F,fontSize:48});
factory.createTextLines(useTextLines);
}
private function useTextLines( tl:DisplayObject ):void
{
_lines.push(tl);
TestCanvas.rawChildren.addChild( tl );
}
public function recycleLineByCustomLineCreatorTextFlow():void
{
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
//Create a TextFlow
var textFlow:TextFlow = new TextFlow();
textFlow.mxmlChildren = [ "Hello, World" ];
var textContainer:Sprite = new Sprite();
var textController:ContainerController = new CustomContainerController(textContainer, 800, 1000);
textFlow.flowComposer.addController(textController);
//monitor if the TextLine created from recycler
var myswfContext:MySwfContext = new MySwfContext()
textFlow.flowComposer.swfContext = myswfContext;
textFlow.flowComposer.updateAllControllers();
//check if composed line is same as recycled line and if createTextLine gets the recycled line
composedTextLine = textFlow.flowComposer.getLineAt(0).getTextLine();
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine
&& myswfContext.numRecycledLines == 1);
//monitor if the TextLine created from new
textFlow.mxmlChildren = [ "Again, Hello, World " ];
textFlow.flowComposer.swfContext = myswfContext;
textFlow.flowComposer.updateAllControllers();
assertTrue("The composed line is not newly created", myswfContext.numLinesCreated == 1);
TestCanvas.rawChildren.addChild(DisplayObject(textContainer));
}
public function recycleLineByTCM():void
{
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
//create a TextFlow by TCM using the recycled line
var sprite:Sprite = new Sprite();
sprite.x = 50; sprite.y = 50;
var tcm:TextContainerManager = new TextContainerManager(sprite);
tcm.setText("Hello World");
tcm.updateContainer();
var editManager:EditManager = EditManager(tcm.beginInteraction())
editManager.selectRange(0, 0);
var textFlow:TextFlow = tcm.getTextFlow();
//check if the composed line is same as the recycled one
composedTextLine = textFlow.flowComposer.getLineAt(0).getTextLine();
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine);
TestCanvas.rawChildren.addChild(DisplayObject(sprite));
TestCanvas.rawChildren.addChild(sprite);
}
public function recycleLineByCustomLineCreatorFlowFactory():void
{
_lines = new Array();
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
var factory:TextFlowTextLineFactory = new TextFlowTextLineFactory();
factory.compositionBounds = new Rectangle( 100, 100, 200, 130 );
//Create a TextFlow
var flow:TextFlow = new TextFlow();
flow.mxmlChildren = [ "Hello, World" ];
//create custom TextLine creator
var myswfContext:MySwfContext = new MySwfContext()
flow.flowComposer.swfContext = myswfContext;
factory.swfContext = flow.flowComposer.swfContext;
//compose a single line which should be from recycler using FlowFactory
factory.createTextLines(useTextLines, flow );
//check if the composed line is same as the recycled one
composedTextLine = _lines[0];
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine
&& myswfContext.numRecycledLines == 1);
//monitor if the TextLine created from new
flow.mxmlChildren = [ "Again, Hello, World " ];
factory.compositionBounds = new Rectangle( 100, 200, 200, 130 );
factory.createTextLines(useTextLines, flow );
assertTrue("The composed line is not newly created", myswfContext.numLinesCreated == 1);
}
public function recycleLineByCustomLineCreatorStringFactory():void
{
_lines = new Array();
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
var factory:StringTextLineFactory = new StringTextLineFactory();
factory.compositionBounds = new Rectangle( 100, 100, 200, 130 );
factory.text = "Hello World";
//create custom TextLine creator
var myswfContext:MySwfContext = new MySwfContext()
factory.swfContext = myswfContext;
//compose a single line which should be from recycler using FlowFactory
factory.createTextLines(useTextLines);
//check if the composed line is same as the recycled one
composedTextLine = _lines[0];
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine
&& myswfContext.numRecycledLines == 1);
//monitor if the TextLine created from new
factory.text = "Again, Hello World";
factory.compositionBounds = new Rectangle( 100, 200, 200, 130 );
factory.createTextLines(useTextLines);
assertTrue("The composed line is not newly created", myswfContext.numLinesCreated == 1);
}
public function recycleLineByCustomLineCreatorTCM():void
{
_lines = new Array();
//create an invald TextLine to recycle
textLine_invalid = createInvalidTextLine();
//recycle the invalid TextLine
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.addLineForReuse(textLine_invalid);
recycledTextLine = textLine_invalid;
//create a TextFlow by TCM using the recycled line
var sprite:Sprite = new Sprite();
sprite.x = 50; sprite.y = 50;
var tcm:TextContainerManager = new TextContainerManager(sprite);
tcm.setText("Hello World");
tcm.updateContainer();
var editManager:EditManager = EditManager(tcm.beginInteraction());
editManager.selectRange(0, 0);
var textFlow:TextFlow = tcm.getTextFlow();
//check if the composed line is same as the recycled one
composedTextLine = textFlow.flowComposer.getLineAt(0).getTextLine();
assertTrue("The composed line is not same as recycled line.", recycledTextLine === composedTextLine);
TestCanvas.rawChildren.addChild(sprite);
}
public function recycleLineInSuite():void
{
var alice:ByteArrayAsset = new AliceClass();
var aliceData:String = alice.readMultiByte(alice.length,"utf-8");
var textFlow:TextFlow = TextConverter.importToFlow(aliceData, TextConverter.TEXT_LAYOUT_FORMAT);
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.textLineRecyclerEnabled = false;
var s:Sprite = new Sprite();
s.x = 50; s.y = 50;
var tcm:TextContainerManager = new TextContainerManager(s);
tcm.compositionWidth = 500;
tcm.compositionHeight = NaN;
tcm.setTextFlow(textFlow);
tcm.updateContainer();
displayobject = testApp.getDisplayObject();
var bits:BitmapData = new BitmapData(displayobject.width, displayobject.height);
bits.draw(TestDisplayObject as IBitmapDrawable);
bitmapSnapshot = new Bitmap(bits);
bits = null;
var pixels:ByteArray = bitmapSnapshot.bitmapData.getPixels(bitmapSnapshot.bitmapData.rect);
pixels.compress();
pixels.position = 0;
var checksumRecyclingOff:String = MD5.hashBinary(pixels);
//create a bunch(100) of invald TextLines to recycle
TextLineRecycler.emptyReusableLineCache();
TextLineRecycler.textLineRecyclerEnabled = true;
var i:int = 0;
while (i<=100)
{
var textLine_invalid:TextLine = createInvalidTextLine();
TextLineRecycler.addLineForReuse(textLine_invalid);
i++;
}
//recompose the text flow with the recycled lines
tcm.updateContainer();
//get checksum for recycling on
var bits_2:BitmapData = new BitmapData(displayobject.width, displayobject.height);
bits_2.draw(TestDisplayObject as IBitmapDrawable);
bitmapSnapshot = new Bitmap(bits_2);
bits_2 = null;
pixels = bitmapSnapshot.bitmapData.getPixels(bitmapSnapshot.bitmapData.rect);
pixels.compress();
pixels.position = 0;
var checksumRecyclingOn:String = MD5.hashBinary(pixels);
//check if there is any rendering difference
assertTrue("the rendering changed between recycle on and off.", checksumRecyclingOn == checksumRecyclingOff);
TestCanvas.rawChildren.addChild(DisplayObject(s));
}
private var tf:TextFlow = new TextFlow();
public function embeddedInlineGraphics(callback:Object = null):void
{
if(!callback)
{
callback = true;
tf.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,addAsync(embeddedInlineGraphics,2500,null),false,0,true);
var TestCanvas:Canvas;
TestDisplayObject = testApp.getDisplayObject();
if (TestDisplayObject)
{
TestCanvas = Canvas(TestDisplayObject);
}
var container:Sprite = new Sprite();
TestCanvas.rawChildren.addChild(container);
var p:ParagraphElement = new ParagraphElement();
var span:SpanElement = new SpanElement();
// add text to the span
span.text = "AAAAAAAA";
p.addChild(span);
tf.addChild(p);
// update controller to display text
var controller:ContainerController = new CustomContainerController(container, 400, 200);
tf.flowComposer.addController(controller);
tf.flowComposer.updateAllControllers();
var src:String = "smiley.gif";
var width:int = 20;
var height:int = 20;
var baseImageURL:String = LoaderUtil.createAbsoluteURL(baseURL, "../../test/testFiles/assets/");
var selectManager:IEditManager = new EditManager();
tf.interactionManager = selectManager;
selectManager.setFocus();
selectManager.selectRange(3, 3);
var inlineGraphicElement:InlineGraphicElement = selectManager.insertInlineGraphic(LoaderUtil.createAbsoluteURL(baseImageURL,src),width,height);
tf.flowComposer.updateAllControllers();
}
else // Make sure the image is ready before we let the snapshot go
{
var img:InlineGraphicElement = tf.findLeaf(3) as InlineGraphicElement;
if(img.status != InlineGraphicElementStatus.READY)
{
tf.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,addAsync(embeddedInlineGraphics,2500,null),false,0,true);
}
}
}
}
}
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.DisplayObjectContainer;
import flash.text.engine.TextLine;
import flashx.textLayout.container.ContainerController;
import flash.filters.*;
import flashx.textLayout.tlf_internal;
import flash.display.DisplayObject;
use namespace tlf_internal;
class CustomContainerController extends ContainerController
{
public function CustomContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100)
{
super(container,compositionWidth,compositionHeight);
// We'll put all text lines in a nested container
// Filters applied to this container won't affect other objects like selection or background shapes
_textLineContainer = new Sprite();
//_textLineContainer.filters = [ new DropShadowFilter() ]; // apply a filter (for illustration)
container.addChild(_textLineContainer);
}
// Return the index where the first text line should appear in its parent
// Since our _textLineContainer only holds text lines, return zero
protected override function getFirstTextLineChildIndex():int
{
return 0;
}
// Add a text line at the specified index
protected override function addTextLine(textLine:TextLine, index:int):void
{
if(index == 0)
textLine.filters = [ new BlurFilter(3, 3, BitmapFilterQuality.HIGH) ];
_textLineContainer.addChildAt(textLine, index);
}
protected override function addInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject, index:int):void
{
parent.addChildAt(inlineGraphicElement, index);
}
// Remove a text line, but only if it is in _textLineContainer
// (A text line may have moved to another container because of 'shuffling')
protected override function removeTextLine(textLine:TextLine):void
{
if (_textLineContainer.contains(textLine))
{
textLine.filters = null;
_textLineContainer.removeChild(textLine);
}
}
// Add the container for selection shapes (block or point selection)
protected override function addSelectionContainer(selectionContainer:DisplayObjectContainer):void
{
// If selection container is opaque or has normal blend mode, put selection container behind the text lines, else in front
var filter:BlurFilter = new BlurFilter(10, 10, BitmapFilterQuality.HIGH);
var myFilters:Array = new Array();
myFilters.push(filter);
selectionContainer.filters = myFilters;
var index:int = selectionContainer.blendMode == BlendMode.NORMAL && selectionContainer.alpha == 1 ? container.getChildIndex(_textLineContainer) : container.numChildren;
container.addChildAt(selectionContainer, index);
}
// Remove the container for selection shapes
protected override function removeSelectionContainer(selectionContainer:DisplayObjectContainer):void
{
container.removeChild(selectionContainer);
}
// Add the background shape
protected override function addBackgroundShape(shape:Shape):void
{
container.addChildAt(shape, 0); // behind everything else, so use index 0
}
private var _textLineContainer:Sprite;
}
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.compose.ISWFContext;
import flash.text.engine.TextBlock;
import flashx.textLayout.elements.Configuration;
class MySwfContext implements ISWFContext
{
public var numLinesCreated:int = 0;
public var numRecycledLines:int = 0;
public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
{
var textBlock:TextBlock = thisArg as TextBlock;
if (textBlock)
{
if (fn == textBlock.createTextLine)
{
numLinesCreated++; // COUNT: create a new TextLine
}
else if (Configuration.playerEnablesArgoFeatures && fn == thisArg["recreateTextLine"])
{
numRecycledLines++; // COUNT: make a TextLine using a recycled line
}
}
if (returns)
return fn.apply(thisArg, argsArray);
fn.apply(thisArg, argsArray);
}
}