Affichage de texte avec Uniscribe

Vos applications peuvent utiliser des fonctions d’API Uniscribe pour prendre en charge la typographie, l’affichage et la modification de texte international. Uniscribe utilise le paragraphe comme unité pour l’affichage de texte et la fonctionnalité Uniscribe doit être utilisée pour l’ensemble du paragraphe.

Lorsque vous utilisez Uniscribe pour afficher du texte, une application doit passer par un processus de mise en forme (« disposition »), généralement à l’aide d’Uniscribe. L’application divise un paragraphe de texte en chaînes de caractères avec le même style. Ce sont les « exécutions ». Le style est déterminé par l’implémentation elle-même, mais il inclut généralement des attributs comme la police, la taille et la couleur. Lors de la définition des exécutions, l’application peut également appliquer d’autres informations, telles que les données de langue et de paramètres régionaux conservées pour une utilisation avec des outils lexicaux. Par exemple, une application peut traiter un passage en français dans un texte principalement en anglais comme une exécution distincte.

Une fois qu’elle a déterminé les exécutions pour tous les paragraphes, l’application divise chaque paragraphe en chaînes qui ont le même script et la même direction (« éléments »). L’application applique les informations des éléments pour produire des exécutions au script et à la direction uniques et qui se trouvent entièrement dans un seul élément (« plages »).

La répartition d’un élément en plages est quelque peu arbitraire, bien qu’une plage se compose d’un ou plusieurs regroupements de caractères alphabétiques définis par un script consécutif, appelé « clusters ». Pour les langues européennes, un cluster correspond généralement à un caractère de page de codes unique ou à un point de code Unicode, et se compose d’un seul glyphe. Toutefois, dans les langues telles que le thaï, un cluster est un regroupement de glyphes et correspond à plusieurs caractères consécutifs ou points de code. Par exemple, un cluster thaïlandais peut contenir une consonne, une voyelle et une marque de ton. Afin de ne pas interrompre de clusters, l’application doit généralement utiliser les plages les plus longues qu’elle peut ou utiliser ses propres informations lexicales pour créer des césures entre les plages à des emplacements ne se trouvant pas au milieu d’un cluster.

Une fois les clusters de chaque plage identifiés, l’application doit déterminer la taille de chaque cluster. Elle utilise Uniscribe pour additionner les clusters et déterminer la taille de chaque plage. Ensuite, l’application additionne les tailles des plages jusqu’à ce qu’elles dépassent une ligne, c’est-à-dire, jusqu’à ce qu’elles atteignent la marge. La plage qui dépasse la ligne est divisée entre la ligne actuelle et la ligne suivante. L’application génère pour chaque ligne une carte de la position visuelle à la position logique pour chaque plage. Ensuite, l’application convertit les points de code pour chaque plage en glyphes, qu’elle peut ensuite positionner et afficher.

Une application ne procède à la mise en page d’un texte qu’une seule fois. Ensuite, soit elle enregistre les glyphes et les positions à des fins d’affichage, soit elle les génère chaque fois qu’elle affiche le texte. Cependant, cela requiert un compromis de vitesse et de mémoire. Une application classique implémente le processus de disposition une seule fois, puis génère les glyphes et les positions chaque fois qu’elle affiche le texte.

Une application qui utilise des scripts complexes connaît les problèmes suivants avec une approche simple de la disposition et de l’affichage.

  • La largeur d’un caractère de script complexe dépend de son contexte. Il n’est pas possible d’enregistrer les largeurs dans des tableaux simples.
  • La rupture entre les mots dans des scripts tels que le thaï nécessite la prise en charge du dictionnaire. Par exemple, aucun caractère séparateur n’est utilisé entre les mots thaïlandais.
  • L’arabe, l’hébreu, le persan, l’ourdou et d’autres langues bidirectionnelles nécessitent une réorganisation avant d’être affichées.
  • Un type d’association de polices est souvent nécessaire pour utiliser facilement des scripts complexes.

L’utilisation du paragraphe comme unité d’affichage par Uniscribe aide l’application à traiter adéquatement ces problèmes de script complexes.

Remarque

Il faut utiliser Uniscribe pour un paragraphe entier, même si les sections du paragraphe ne sont pas des scripts complexes.

 

Comme indiqué dans le tableau suivant, la version 1.6 d’Uniscribe et les versions ultérieures prennent en charge plusieurs fonctions qui tirent parti des balises OpenType. Elles peuvent être remplacées par les fonctions classiques Uniscribe correspondantes. En règle générale, vos applications doivent fonctionner entièrement avec les fonctions d’un des deux ensembles et ne doivent pas tenter de « combiner ou de faire correspondre » les fonctions.

Fonction Uniscribe classique Fonction OpenType équivalente
ScriptItemize ScriptItemizeOpenType
ScriptShape ScriptShapeOpenType
ScriptPlace ScriptPlaceOpenType

 

Mettre en page du texte à l’aide d’Uniscribe

Votre application peut utiliser les étapes suivantes pour mettre en place un paragraphe de texte avec Uniscribe. Cette procédure suppose que l’application a déjà divisé le paragraphe en exécutions.

  1. Appelez ScriptRecordDigitSubstitution uniquement au démarrage ou lors de la réception d’un message WM_SETTINGCHANGE.

  2. (Facultatif) Appelez ScriptIsComplex pour déterminer si le paragraphe nécessite un traitement complexe.

  3. (Facultatif) Si vous utilisez Uniscribe pour gérer le texte bidirectionnel et/ou la substitution de chiffres, appelez ScriptApplyDigitSubstitution pour préparer les structures SCRIPT_CONTROL et SCRIPT_STATE en tant qu’entrées à ScriptItemize. Si vous ignorez cette étape, mais que vous cherchez toujours une substitution de chiffres, remplacez les chiffres nationaux d’Unicode U+0030 à U+0039 (les chiffres européens). Pour plus d’informations sur la substitution de chiffres, consultez Formes de chiffres.

  4. Appelez ScriptItemize pour diviser le paragraphe en éléments. Si vous n’utilisez pas Uniscribe pour la substitution de chiffres et que l’ordre bidirectionnel est connu, par exemple, en raison de la disposition du clavier utilisée pour entrer le caractère, appelez ScriptItemize. Dans l’appel, fournissez des pointeurs null pour les structures SCRIPT_CONTROL et SCRIPT_STATE. Cette technique génère des éléments uniquement à l’aide du moteur de mise en forme, et les éléments peuvent être réorganisés à l’aide des informations du moteur.

    Remarque

    En règle générale, les applications qui fonctionnent uniquement avec des scripts de gauche à droite et sans substitution de chiffres doivent passer des pointeurs null pour les structures SCRIPT_CONTROL et SCRIPT_STATE.

     

  5. Fusionnez les informations d’élément avec les informations d’exécution pour produire des plages.

  6. Appelez ScriptShape pour identifier les clusters et générer des glyphes.

  7. Si ScriptShape renvoie le code USP_E_SCRIPT_NOT_IN_FONT ou S_OK avec le résultat contenant des glyphes manquants, sélectionnez des caractères d’une autre police. Choisissez une autre police ou désactivez la mise en forme en définissant le membre eScript de la structure SCRIPT_ANALYSIS passée à ScriptShape pour SCRIPT_UNDEFINED. Pour plus d’informations, consultez Utilisation de Police de remplacement.

  8. Appelez ScriptPlace pour générer des largeurs avancées et des positions x et y pour les glyphes dans chaque plage successive. Il s’agit de la première étape pour laquelle il requiert de prendre en considération la taille du texte.

  9. Additionnez les tailles de plage jusqu’au dépassement de la ligne.

  10. Arrêtez la plage à la limite d’un mot à l’aide des membres fSoftBreak et fWhiteSpace dans les attributs logiques. Pour interrompre une seule exécution d’un cluster de caractères, utilisez les informations renvoyées en appelant ScriptBreak.

    Remarque

    Déterminez si le premier point de code d’une plage doit être un point d’arrêt de mot, car le dernier caractère de la plage précédente l’exige. Par exemple, si une plage se termine par une virgule, considérez le premier caractère de la plage suivante comme un point d’arrêt de mot.

     

  11. Répétez les étapes 6 à 10 pour chaque ligne du paragraphe. Toutefois, en cas de rupture de la dernière exécution sur la ligne, appelez ScriptShape pour remodeler la partie restante de l’exécution en tant que première exécution sur la ligne suivante.

Mettre en page du texte à l’aide d’Uniscribe

Votre application peut utiliser les étapes suivantes pour afficher un paragraphe de texte. Cette procédure suppose que le texte a déjà été disposé par l’application et que celle-ci n’a pas enregistré les glyphes et les positions du processus de disposition. Si vous voulez aller plus vite, l’application peut enregistrer les glyphes et les positions de la procédure de disposition et commencer à l’étape 2 de la procédure d’affichage.

Remarque

L’application peut omettre l’étape 2 si le texte ne contient aucun caractère de scripts de droite à gauche, ainsi qu’aucun caractère de contrôle bidirectionnel et qu’elle utilise un niveau d’incorporation de base de gauche à droite.

 

  1. Pour chaque exécution, procédez comme suit :

    1. Si le style a changé depuis la dernière exécution, mettez à jour la gestion du contexte de l’appareil en la libérant et en la réexécutant.
    2. Appelez ScriptShape pour générer des glyphes pour l’exécution.
    3. Appelez ScriptPlace pour générer une largeur avancée et un décalage x,y pour chaque glyphe.
  2. Procédez comme suit pour établir l’ordre visuel correct pour les exécutions dans la ligne :

    1. Extrayez un tableau de niveaux d’incorporation bidirectionnels, un par plage. Le niveau d’incorporation est donné par (SCRIPT_ITEM) si.(SCRIPT_ANALYSIS) a. (SCRIPT_STATE) s.uBidiLevel.
    2. Transmettez ce tableau à ScriptLayout pour générer une carte associant les positions visuelles aux positions logiques.
  3. (Facultatif) Pour justifier le texte, appelez ScriptJustify ou utilisez des connaissances spécialisées du texte.

  4. Utilisez la carte visuelle-logique pour afficher les exécutions dans l’ordre visuel. À partir du côté gauche de la ligne, appelez ScriptTextOut pour afficher l’exécution donnée par la première entrée de la carte. Pour chaque entrée suivante de la carte, appelez ScriptTextOut pour afficher l’exécution indiquée à droite de l’exécution précédente.

    Si vous omettez l’étape 2, commencez à gauche de la ligne et appelez ScriptTextOut pour afficher la première exécution logique, puis pour afficher chaque exécution logique à droite de l’exécution précédente.

  5. Répétez les étapes ci-dessus pour toutes les lignes du paragraphe.

Utilisation d’Uniscribe