Perché abbiamo affidato il rendering dei caratteri alla piattaforma invece di disegnarli direttamente
Vi è mai capitato che l’hangul apparisse perfettamente normale, mentre soltanto gli hanja sembravano in qualche modo insoliti? Se decidiamo di non disegnare direttamente i caratteri e di affidarci al motore di testo della piattaforma, il nostro lavoro non consiste più nello stabilire «che cosa disegnare», ma «quale font chiedere».

Prima che il testo appaia sullo schermo devono avvenire molte operazioni. Bisogna trasformare i caratteri in forme, suddividere le righe e disegnarle in pixel. È necessario gestire tutto: dalla composizione dell’hangul agli hanja, alle emoji, alla scrittura araba e al fallback dei font.
Non abbiamo ricreato da zero questo processo. Lo abbiamo affidato a Pango e HarfBuzz su Linux, a DirectWrite su Windows e a TextKit 2 su macOS.
Perché è un ambito che i sistemi operativi perfezionano da molto tempo. Se lo avessimo sviluppato direttamente, ci sarebbe stata un’elevata probabilità di peggiorare la qualità proprio negli aspetti più complessi, come i caratteri CJK o l’accessibilità. Inoltre, ritenevamo che l’elemento distintivo del prodotto non fosse il renderer in sé, ma la tipografia e un’esperienza d’uso coerente con ciascuna piattaforma.
Abbiamo però deciso noi quando creare il layout
Creare il layout del testo richiede tempo e memoria. Nei documenti di grandi dimensioni possono esserci decine di migliaia di righe, quindi non potevamo crearle tutte.
Per questo creiamo soltanto le righe visibili sullo schermo e quelle nelle vicinanze. Le righe che si allontanano dallo schermo vengono eliminate immediatamente. Anche scorrendo a lungo un documento da 1 MB, rimangono attivi soltanto dai quaranta ai sessanta layout circa.
Per le righe non ancora create, stimiamo in anticipo l’altezza. La barra di scorrimento deve infatti conoscere la lunghezza complessiva del documento.
Naturalmente, a volte la stima è sbagliata. Se l’altezza appena calcolata è diversa da quella prevista, il contenuto sullo schermo può spostarsi. In quel caso correggiamo la posizione di scorrimento della stessa differenza all’interno del medesimo fotogramma. Agli occhi dell’utente non deve essere successo nulla.
Le righe in cui si sta componendo l’hangul vengono disegnate senza decorazioni. Questo perché, se durante l’immissione si inseriscono attributi come il grassetto o il testo nascosto, il numero di caratteri noto al metodo di input può diventare diverso da quello mostrato sullo schermo.
Il primo problema che abbiamo incontrato è stato il volto degli hanja
Affidandosi alla piattaforma, se ne ereditano anche le impostazioni predefinite.
Il font predefinito dell’interfaccia di Ubuntu non contiene l’hangul. Per questo il font scelto in sostituzione dal sistema era Noto Sans CJK JP. L’hangul appariva correttamente, ma alcuni hanja venivano visualizzati con glifi giapponesi. Questo accade perché alcuni caratteri, pur avendo lo stesso codice Unicode, hanno forme diverse in Corea e in Giappone.
La soluzione è stata semplice. Abbiamo messo Noto Sans CJK KR all’inizio dell’elenco dei font dell’interfaccia.
Ma c’era un aspetto ancora più importante. Se non stabiliamo noi il criterio, la piattaforma risponde in base alle proprie impostazioni predefinite, non alla lingua dell’utente.
Creiamo forme adatte a ogni lingua attraverso l’ordine dei font
Uno stack di font cerca i caratteri a partire dal primo font. Soltanto i caratteri assenti dal primo font passano a quello successivo.
Sfruttando questa proprietà, possiamo mostrare i caratteri latini con un font serif e l’hangul con un font sans serif. Con una sola riga di configurazione combiniamo font adatti a ciascuna lingua.
Se il font di lettura viene lasciato vuoto, utilizziamo senza modifiche il font del corpo del testo. Se viene specificato separatamente, cambia soltanto nella modalità di lettura. Nella modalità sorgente utilizziamo il font del codice.
La dimensione dei caratteri segue le impostazioni di accessibilità del sistema operativo. Chi ha ingrandito i caratteri nelle impostazioni di sistema non deve configurarli di nuovo in ogni applicazione.

Anche lo screen reader sfrutta la stessa base. Poiché le funzioni di accessibilità sono già collegate al livello testuale della piattaforma, noi dobbiamo soltanto trasmettere con precisione il contenuto della riga richiesta.
Se manca una traduzione, la build fallisce
Le frasi dell’interfaccia vengono scritte in inglese e quelle stesse frasi vengono usate come chiavi della tabella delle traduzioni. Se manca una traduzione, sullo schermo appare direttamente il testo inglese.
Il problema è che non si verifica alcun errore. Anche quando manca una traduzione, l’inglese compare silenziosamente mescolato alle altre lingue.
Per questo abbiamo creato uno script di verifica. Raccoglie le frasi effettivamente utilizzate nel codice e le confronta con le tabelle di traduzione di 12 lingue. Se una frase viene aggiunta a una sola lingua o se si dimentica una traduzione, la build fallisce.
Ogni tabella di traduzione contiene 304 chiavi, mentre le frasi effettivamente utilizzate nel codice sono 282. Le lingue supportate sono English, 한국어, 日本語, 简体中文, 繁體中文, Deutsch, Français, Español, Português (Brasil), Русский, Italiano, Polski.

Quando si cambia lingua, apriamo una nuova finestra con lo stesso documento e chiudiamo quella esistente. Traducendo uno per uno le centinaia di widget già presenti, aumenterebbe la probabilità di dimenticarne qualcuno. Abbiamo ritenuto più sicuro riaprire una volta la finestra nel momento in cui si cambia lingua, invece di mantenere un percorso complesso usato molto raramente.
Affidandosi alla piattaforma, anche il risultato le assomiglia
Anche con lo stesso documento, i pixel non sono perfettamente identici su tutti i sistemi operativi. Questo accade perché cambiano il modo in cui vengono rifiniti i caratteri e i font predefiniti.
Non cerchiamo di renderli uguali a tutti i costi. Manteniamo invece uniformi i criteri del documento, come le proporzioni delle dimensioni dei caratteri, l’altezza delle righe e i margini.
Anche il risultato del fallback può cambiare in base ai font installati. Per questo, invece di promettere un risultato specifico, mostriamo in modo trasparente l’ordine in cui vengono richiesti i font. E l’utente può anche modificarlo direttamente.
Il fatto di non disegnare direttamente i caratteri non fa scomparire anche la responsabilità. Dobbiamo stabilire con maggiore precisione che cosa affidare alla piattaforma e in quale ordine effettuare le richieste.