//////////////////////////////////////////////////////////////////////////////// // // 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 flashx.textLayout.compose { import flash.text.engine.TextBlock; import flash.text.engine.TextLine; import flash.text.engine.TextLineValidity; import flash.utils.Dictionary; CONFIG::debug { import flashx.textLayout.debug.assert; } import flashx.textLayout.tlf_internal; use namespace tlf_internal; /** * The TextLineRecycler class provides support for recycling of TextLines. Some player versions support a recreateTextLine. Passing TextLines * to the recycler makes them available for reuse. This improves Player performance. * * @playerversion Flash 10 * @playerversion AIR 1.5 * @langversion 3.0 */ public class TextLineRecycler { static private const _textLineRecyclerCanBeEnabled:Boolean = (new TextBlock).hasOwnProperty("recreateTextLine"); static private var _textLineRecyclerEnabled:Boolean = _textLineRecyclerCanBeEnabled; /** Controls if the TLF recycler enabled. It can only be enabled in 10.1 or later players. * @playerversion Flash 10 * @playerversion AIR 1.5 * @langversion 3.0 */ static public function get textLineRecyclerEnabled():Boolean { return _textLineRecyclerEnabled; } static public function set textLineRecyclerEnabled(value:Boolean):void { _textLineRecyclerEnabled = value ? _textLineRecyclerCanBeEnabled : false; } // manage a cache of TextLine's that can be reused // This version uses a dictionary that holds the TextLines as weak references static private var reusableLineCache:Dictionary = new Dictionary(true); /** * Add a TextLine to the pool for reuse. TextLines for reuse should have null userData and null parent. * @playerversion Flash 10 * @playerversion AIR 1.5 * @langversion 3.0 */ static public function addLineForReuse(textLine:TextLine):void { CONFIG::debug { assert(textLine.parent == null && textLine.userData == null && (textLine.validity == TextLineValidity.INVALID || textLine.validity == TextLineValidity.STATIC),"textLine not ready for reuse"); } if (_textLineRecyclerEnabled) { CONFIG::debug { for each (var line:TextLine in reusableLineCache) { assert(line != textLine,"READDING LINE TO CACHE"); } } CONFIG::debug { cacheTotal++; } reusableLineCache[textLine] = null; } } CONFIG::debug { /** @private */ static tlf_internal var cacheTotal:int = 0; /** @private */ static tlf_internal var fetchTotal:int = 0; /** @private */ static tlf_internal var hitTotal:int = 0; static private function recordFetch(hit:int):void { fetchTotal++; hitTotal += hit; /*if ((fetchTotal%100) == 0) trace(fetchTotal,hitTotal,cacheTotal);*/ } } /** * Return a TextLine from the pool for reuse. * @playerversion Flash 10 * @playerversion AIR 1.5 * @langversion 3.0 */ static public function getLineForReuse():TextLine { if (_textLineRecyclerEnabled) { for (var obj:Object in reusableLineCache) { // remove from the cache delete reusableLineCache[obj]; CONFIG::debug { assert(reusableLineCache[obj] === undefined,"Bad delete"); } CONFIG::debug { recordFetch(1); } return obj as TextLine; } CONFIG::debug { recordFetch(0); } } return null; } /** @private empty the reusableLineCache */ static tlf_internal function emptyReusableLineCache():void { reusableLineCache = new Dictionary(true); } } }