Rendering text objects

Use the bitmap caching feature and the opaqueBackground property to improve text rendering performance.

The Flash Text Engine provides some great optimizations. However, numerous classes are required to show a single line of text. For this reason, creating an editable text field with the TextLine class requires a great deal of memory and many lines of ActionScript code. The TextLine class is best used for static and non-editable text, for which it renders faster and requires less memory.

The bitmap caching feature allows you to cache vector content as bitmaps to improve rendering performance. This feature is helpful for complex vector content and also when used with text content that requires processing to be rendered.

The following example shows how the bitmap caching feature and the opaqueBackground property can be used to improve rendering performance. The following figure illustrates a typical Welcome screen that can be displayed when a user is waiting for something to load:

The following figure illustrates the easing that is applied to the TextField object programmatically. The text eases slowly from the top of the scene to the center of the scene:

The following code creates the easing. The preloader variable stores the current target object to minimize property lookups, which can hurt performance:

wait_mc.addEventListener( Event.ENTER_FRAME, movePosition ); 
  
var destX:Number=stage.stageWidth/2; 
var destY:Number=stage.stageHeight/2; 
var preloader:DisplayObject; 
  
function movePosition( e:Event ):void 
{ 
    preloader = e.currentTarget as DisplayObject; 
     
    preloader.x -= ( preloader.x - destX ) * .1; 
    preloader.y -= ( preloader.y - destY ) * .1; 
     
    if (Math.abs(preloader.y-destY)<1) 
        preloader.removeEventListener( Event.ENTER_FRAME, movePosition ); 
}

The Math.abs() function could be moved inline here to reduce the number of function calls and get more performance improvements. A best practice is to use the int type for the destX and destY properties, so that you have fixed-point values. Using the int type allows you to get perfect pixel snapping without having to round values manually through slow methods like Math.ceil() or Math.round() . This code doesn’t round the coordinates to int, because by rounding the values constantly, the object does not move smoothly. The object can have jittery movements, because the coordinates are snapped to the nearest rounded integers on every frame. However, this technique can be useful when setting a final position for a display object. Don’t use the following code:

// Do not use this code 
var destX:Number = Math.round ( stage.stageWidth / 2 );  
var destY:Number = Math.round ( stage.stageHeight / 2); 

The following code is much faster:

var destX:int = stage.stageWidth / 2;  
var destY:int = stage.stageHeight / 2; 

The previous code can be optimized even further, by using bitwise-shifting operators to divide the values:

var destX:int = stage.stageWidth >> 1;  
var destY:int = stage.stageHeight >> 1;

The bitmap caching feature makes it easier for the runtime to render objects by using dynamic bitmaps. In the current example, the movie clip containing the TextField object is cached:

wait_mc.cacheAsBitmap = true;

One additional way to improve performance is by removing alpha transparency. Alpha transparency places an additional burden on the runtime when drawing transparent bitmap images, as in the previous code. You can use the opaqueBackground property to bypass that, by specifying a color as a background.

When using the opaqueBackground property, the bitmap surface created in memory still uses 32 bits. However, the alpha offset is set to 255 and no transparency is used. As a result, the opaqueBackground property does not reduce memory usage, but it improves rendering performance when using the bitmap caching feature. The following code contains all of the optimizations:

wait_mc.addEventListener( Event.ENTER_FRAME, movePosition ); 
wait_mc.cacheAsBitmap = true; 
  
// Set the background to the color of the scene background 
wait_mc.opaqueBackground = 0x8AD6FD; 
var destX:int = stage.stageWidth >> 1; 
var destY:int = stage.stageHeight >> 1; 
var preloader:DisplayObject; 
  
function movePosition ( e:Event ):void 
{ 
    preloader = e.currentTarget as DisplayObject; 
     
    preloader.x -= ( preloader.x - destX ) * .1; 
    preloader.y -= ( preloader.y - destY ) * .1; 
     
    if ( Math.abs ( preloader.y - destY ) < 1 ) 
        e.currentTarget.removeEventListener ( Event.ENTER_FRAME, movePosition ); 
}

The animation is now optimized, and the bitmap caching has been optimized by removing transparency. On mobile devices, consider switching the Stage quality to LOW and HIGH during the different states of the animation while using the bitmap caching feature:

wait_mc.addEventListener( Event.ENTER_FRAME, movePosition ); 
wait_mc.cacheAsBitmap = true; 
wait_mc.opaqueBackground = 0x8AD6FD; 
  
// Switch to low quality 
stage.quality = StageQuality.LOW; 
var destX:int = stage.stageWidth>>1; 
var destY:int = stage.stageHeight>>1; 
var preloader:DisplayObject; 
  
function movePosition( e:Event ):void 
{ 
    preloader = e.currentTarget as DisplayObject; 
     
    preloader.x -= ( preloader.x - destX ) * .1; 
    preloader.y -= ( preloader.y - destY ) * .1; 
     
    if (Math.abs(e.currentTarget.y-destY)<1) 
    { 
        // Switch back to high quality 
        stage.quality = StageQuality.HIGH; 
        preloader.removeEventListener( Event.ENTER_FRAME, movePosition ); 
    } 
}

However, in this case, changing the Stage quality forces the runtime to regenerate the bitmap surface of the TextField object to match the current Stage quality. For this reason, it is best to not change the Stage quality when using the bitmap caching feature.

A manual bitmap caching approach could have been used here. To simulate the opaqueBackground property, the movie clip can be drawn to a non-transparent BitmapData object, which does not force the runtime to regenerate the bitmap surface.

This technique works well for content that doesn’t change over time. However, if the content of the text field can change, consider using a different strategy. For example, imagine a text field that is continuously updated with a percentage representing how much of the application has loaded. If the text field, or its containing display object, has been cached as a bitmap, its surface must be generated each time the content changes. You cannot use manual bitmap caching here, because the display object content is constantly changing. This constant change would force you to manually call the BitmapData.draw() method to update the cached bitmap.

Remember that since Flash Player 8 (and AIR 1.0), regardless of the Stage quality value, a text field with rendering set to Anti-Alias for Readability remains perfectly anti-aliased. This approach consumes less memory, but it requires more CPU processing and it renders a little more slowly than the bitmap caching feature.

The following code uses this approach:

wait_mc.addEventListener( Event.ENTER_FRAME, movePosition ); 
  
// Switch to low quality 
stage.quality = StageQuality.LOW; 
var destX:int = stage.stageWidth >> 1; 
var destY:int = stage.stageHeight >> 1; 
var preloader:DisplayObject; 
function movePosition ( e:Event ):void 
{ 
    preloader = e.currentTarget as DisplayObject; 
     
    preloader.x -= ( preloader.x - destX ) * .1; 
    preloader.y -= ( preloader.y - destY ) * .1; 
     
    if ( Math.abs ( preloader.y - destY ) < 1 ) 
    { 
        // Switch back to high quality 
        stage.quality = StageQuality.HIGH; 
        preloader.removeEventListener ( Event.ENTER_FRAME, movePosition ); 
    } 
}

Using this option (Anti-Alias for Readability) for text in motion is not recommended. When scaling the text, this option causes the text tries to stay aligned, which produces a shifting effect. However, if the display object’s content is constantly changing and you need scaled text, you can improve performance in mobile applications by setting the quality to LOW . When the motion finishes, switch the quality back to HIGH .

// Ethnio survey code removed