Pourquoi nous avons confié le rendu des caractères à la plateforme au lieu de les dessiner nous-mêmes
Vous est-il déjà arrivé que le hangeul s’affiche correctement, mais que seuls les caractères chinois paraissent quelque peu inhabituels ? Quand on décide de ne pas dessiner soi-même les caractères et de les confier au moteur de texte de la plateforme, notre travail ne consiste plus à déterminer « quoi dessiner », mais « quelle police demander ».

De nombreuses opérations sont nécessaires avant que le texte apparaisse à l’écran. Il faut transformer les caractères en formes, répartir le texte sur plusieurs lignes et le dessiner en pixels. Il faut tout prendre en charge, de la composition du hangeul aux caractères chinois, aux émojis, à l’écriture arabe et aux polices de substitution.
Nous n’avons pas recréé ce processus. Nous l’avons confié à Pango et HarfBuzz sous Linux, à DirectWrite sous Windows et à TextKit 2 sous macOS.
C’est en effet un domaine que les systèmes d’exploitation perfectionnent depuis longtemps. Si nous l’avions développé nous-mêmes, nous aurions probablement dégradé la qualité dans des domaines délicats comme les caractères CJK ou l’accessibilité. Nous estimions aussi que ce qui distinguait le produit ne résidait pas dans le moteur de rendu lui-même, mais dans la typographie et dans une expérience d’utilisation propre à chaque plateforme.
En revanche, c’est nous qui avons décidé quand les créer
La création d’une mise en page de texte demande du temps et de la mémoire. Les grands documents comptent parfois des dizaines de milliers de lignes, si bien qu’il était impossible de toutes les créer.
Nous ne créons donc que les lignes visibles à l’écran et celles qui les entourent. Et nous supprimons immédiatement celles qui s’en éloignent. Même après avoir longtemps fait défiler un document de 1 Mo, il ne reste qu’une quarantaine à une soixantaine de mises en page actives.
Pour les lignes qui n’ont pas encore été créées, nous estimons leur hauteur à l’avance. Car la barre de défilement doit connaître la longueur totale du document.
Bien sûr, il arrive que l’estimation soit incorrecte. Si la hauteur recalculée diffère de celle prévue, l’affichage peut se décaler. Dans ce cas, nous corrigeons la position de défilement de la différence au cours de la même image. Aux yeux de l’utilisateur, rien ne doit s’être produit.
Les lignes où du hangeul est en cours de composition sont affichées sans mise en forme. En effet, si des propriétés comme le gras ou le masquage interviennent pendant la saisie, le nombre de caractères connu par la méthode de saisie peut différer du nombre de caractères affichés à l’écran.
Le premier problème rencontré était le visage des caractères chinois
Confier le rendu à la plateforme implique aussi d’en accepter les valeurs par défaut.
La police d’interface par défaut d’Ubuntu ne contient pas de hangeul. Le système a donc choisi à la place la police Noto Sans CJK JP. Le hangeul s’affichait correctement, mais certains caractères chinois apparaissaient sous leur forme japonaise. Cela s’explique par le fait que certains caractères ont une forme différente en Corée et au Japon, même lorsqu’ils correspondent au même caractère Unicode.
La solution était simple. Nous avons placé Noto Sans CJK KR en tête de la liste des polices d’interface.
Mais le plus important était ailleurs. Si nous ne définissons pas nous-mêmes les critères, la plateforme répond en fonction de ses propres valeurs par défaut, et non de la langue de l’utilisateur.
Nous créons des formes adaptées à chaque langue grâce à l’ordre des polices
Une pile de polices recherche les caractères en partant de la première police. Seuls les caractères absents de la première police passent à la suivante.
En exploitant cette propriété, on peut afficher l’alphabet latin avec une police à empattements et le hangeul avec une police sans empattements. Une seule ligne de configuration permet ainsi de combiner des polices adaptées à chaque langue.
Si la police de lecture est laissée vide, la police du corps du texte est utilisée telle quelle. Si elle est définie séparément, elle ne change qu’en mode lecture. Le mode source utilise une police de code.
La taille des caractères suit les réglages d’accessibilité du système d’exploitation. Ainsi, les utilisateurs qui ont agrandi les caractères dans le système n’ont pas besoin de recommencer ce réglage dans chaque application.

Le lecteur d’écran repose lui aussi sur la même base. Les fonctions d’accessibilité étant déjà reliées à la couche de texte de la plateforme, il nous suffit de transmettre avec exactitude le contenu de la ligne demandée.
S’il manque une traduction, la compilation échoue
Les phrases de l’interface sont rédigées en anglais, et ces mêmes phrases servent de clés dans la table de traduction. Lorsqu’une traduction manque, la phrase anglaise s’affiche telle quelle à l’écran.
Le problème, c’est qu’aucune erreur ne se produit. Même s’il manque une traduction, de l’anglais se mêle silencieusement au reste du texte.
Nous avons donc créé un script de vérification. Il rassemble les phrases réellement utilisées dans le code et les compare aux tables de traduction de 12 langues. Si une phrase n’est ajoutée que dans une seule langue ou si une traduction est omise, la compilation échoue.
Chaque table de traduction contient 304 clés, dont 282 correspondent à des phrases réellement utilisées dans le code. Les langues prises en charge sont English, 한국어, 日本語, 简体中文, 繁體中文, Deutsch, Français, Español, Português (Brasil), Русский, Italiano et Polski.

Lorsque l’utilisateur change de langue, nous ouvrons une nouvelle fenêtre avec le même document, puis nous fermons l’ancienne. Traduire un à un les centaines de widgets déjà affichés risquerait d’entraîner des oublis. Nous avons estimé qu’il était plus sûr de rouvrir une fois la fenêtre au moment du changement de langue que de maintenir un parcours complexe rarement utilisé.
Quand on confie le rendu à la plateforme, le résultat lui ressemble aussi
Même avec un document identique, les pixels ne sont pas parfaitement les mêmes d’un système d’exploitation à l’autre. Cela s’explique par les différences dans les méthodes de lissage des caractères et dans les polices par défaut.
Nous ne cherchons pas à les rendre identiques de force. Nous veillons plutôt à conserver les mêmes références pour le document, comme les proportions de la taille des caractères, la hauteur des lignes et les marges.
Le résultat de la substitution peut également varier selon les polices installées. Au lieu de promettre un résultat précis, nous affichons donc de manière transparente l’ordre dans lequel les polices sont demandées. L’utilisateur peut aussi le modifier lui-même.
Ne pas dessiner nous-mêmes ne nous décharge pas de toute responsabilité. Nous devons déterminer avec davantage de précision ce que nous confions à la plateforme et dans quel ordre nous formulons nos demandes.