Rendu des objets de texte

Conjuguez la fonction de mise en cache sous forme de bitmap et la propriété opaqueBackground pour améliorer les performances de rendu du texte.

Flash Text Engine propose d’excellentes optimisations. Cependant, de nombreuses classes sont nécessaires pour afficher une seule ligne de texte. Pour créer un champ de texte modifiable à l’aide de la classe TextLine exige donc beaucoup de mémoire et de nombreuses lignes de code ActionScript. Cette classe est mieux adaptée au texte statique non modifiable. Elle assure dans ce cas un rendu plus rapide et consomme moins de mémoire.

La fonction de mise en cache sous forme de bitmap permet de mettre en cache du contenu vectoriel sous forme de bitmaps pour améliorer les performances de rendu. Elle convient au contenu vectoriel complexe et au texte dont le rendu nécessite un traitement préliminaire.

L’exemple suivant montre comment conjuguer la fonction de mise en cache sous forme de bitmap et la propriété opaqueBackground pour améliorer les performances de rendu. La figure ci-dessous illustre un écran de bienvenue standard présenté à l’utilisateur lors du chargement de ressources :

La figure suivante illustre l’accélération appliquée à l’objet TextField par programmation. Le texte est accéléré lentement du haut de la scène vers le centre de celle-ci :

Le code suivant crée l’accélération. La variable preloader stocke l’objet cible actif pour réduire les recherches de propriétés, qui peuvent avoir une incidence sur les performances :

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 ); 
}

Dans cet exemple, vous pourriez placer la fonction Math.abs() en ligne pour réduire le nombre des appels de fonction et améliorer encore plus les performances. Il est recommandé de définir les propriétés destX et destY sur le type int pour obtenir des valeurs à virgule fixe. L’utilisation du type int assure un accrochage aux pixels parfait sans avoir à arrondir manuellement les valeurs par le biais de méthodes lentes telles queMath.ceil() ou Math.round(). Ce code n’arrondit pas les coordonnées à des valeurs entières car, en conséquence d’un arrondissement constant, le déplacement de l’objet n’est pas fluide. Ses mouvements peuvent être saccadés, car les coordonnées sont accrochées aux entiers arrondis les plus proches sur chaque image. Cette technique peut cependant être utile pour définir la position finale d’un objet d’affichage. N’utilisez pas le code suivant :

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

Le code suivant est beaucoup plus rapide :

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

Il est possible d’optimiser encore plus le code précédent en utilisant des opérateurs de décalage au niveau du bit pour diviser les valeurs :

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

Grâce à la fonction de mise en cache sous forme de bitmap, le moteur d’exécution peut utiliser des bitmaps dynamiques, ce qui facilite le rendu des objets. Dans le présent exemple, le clip contenant l’objet TextField est en cache :

wait_mc.cacheAsBitmap = true;

Pour améliorer les performances, vous pouvez aussi supprimer la transparence alpha. Celle-ci surcharge le moteur d’exécution lors de la création d’images bitmap transparentes, comme dans le code précédent. Pour contourner cette difficulté, vous pouvez utiliser la propriété opaqueBackground et spécifier une couleur comme arrière-plan.

Lorsque vous utilisez la propriété opaqueBackground, la surface bitmap créée en mémoire occupe encore 32 bits. Le décalage alpha est toutefois défini sur 255 et aucune transparence n’est appliquée. La propriété opaqueBackground ne permet donc pas de réduire la consommation de mémoire mais, lorsqu’elle est alliée à la fonction de mise en cache sous forme de bitmap, elle améliore les performances de rendu. Le code suivant conjugue toutes les possibilités d’optimisation :

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 ); 
}

L’animation est maintenant optimisée. La mise en cache sous forme de bitmap l’est également en conséquence de la suppression de la transparence. Sur les périphériques mobiles, vous pouvez éventuellement faire passer la qualité de scène de LOW à HIGH (et inversement) au cours des différents états de l’animation tout en utilisant la fonction de mise en cache sous forme de bitmap :

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 ); 
    } 
}

Dans ce cas, le moteur d’exécution doit cependant régénérer la surface bitmap de l’objet TextField afin qu’il corresponde au paramètre de qualité de scène actif. Il est donc préférable de ne pas modifier ce paramètre lorsque vous utilisez la fonction de mise en cache sous forme de bitmap.

Cet exemple se prête également à une technique de mise en cache sous forme de bitmap manuelle. Pour simuler la propriété opaqueBackground, il est possible de dessiner le clip sur un objet BitmapData non transparent ; le moteur d’exécution n’est alors pas obligé de régénérer la surface bitmap.

Cette technique est adaptée au contenu qui ne change pas à terme. En revanche, s’il est possible de modifier le contenu du champ de texte, faites si possible appel à une autre stratégie. Imaginons qu’un champ de texte soit constamment mis à jour pour indiquer le pourcentage de l’application qui est chargé. Si le champ de texte, ou l’objet d’affichage le contenant, a été mis en cache sous forme de bitmap, sa surface doit être générée chaque fois que le contenu change. Il est impossible d’utiliser la mise en cache sous forme de bitmap manuelle dans ce cas, car le contenu de l’objet d’affichage change sans cesse. Vous seriez alors forcé d’appeler manuellement la méthode BitmapData.draw() pour mettre à jour le bitmap mis en cache.

Pour rappel, depuis Flash Player 8 (et AIR 1.0), quelle que soit la valeur de la qualité de scène, un champ de texte dont le rendu est défini sur Anticrènelage pour la lisibilité reste parfaitement anticrènelé. Cette technique est moins gourmande en mémoire mais elle sollicite plus l’unité centrale et le rendu est un peu moins rapide qu’avec la fonction de mise en cache sous forme de bitmap.

Le code suivant repose sur cette technique :

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 ); 
    } 
}

Il est déconseillé d’utiliser l’option Anticrènelage pour la lisibilité pour le texte en mouvement. Lorsqu’elle est conjuguée à une mise à l’échelle du texte, le texte tente de rester aligné, ce qui produit un effet de décalage. Toutefois, si le contenu de l’objet d’affichage change constamment et qu’il est nécessaire de mettre le texte à l’échelle, vous pouvez améliorer les performances sur les applications mobiles en définissant la qualité sur LOW. Au terme du mouvement, redéfinissez la qualité sur HIGH.