Por qué dejamos el renderizado del texto en manos de la plataforma
¿Alguna vez has visto que el hangul se muestra correctamente, pero solo los caracteres chinos parecen algo extraños? Cuando decidimos no dibujar los caracteres directamente y delegar esa tarea en el motor de texto de la plataforma, nuestro trabajo deja de ser «qué dibujar» y pasa a ser «qué fuente pedir».

Para que el texto aparezca en la pantalla hacen falta muchas cosas. Hay que convertir los caracteres en formas, dividirlos en líneas y dibujarlos como píxeles. También hay que gestionar desde la composición del hangul hasta los caracteres chinos, los emojis, la escritura árabe y la sustitución de fuentes.
Nosotros no creamos este proceso desde cero. Se lo confiamos a Pango y HarfBuzz en Linux, DirectWrite en Windows y TextKit 2 en macOS.
Lo hicimos porque es un ámbito que los sistemas operativos llevan mucho tiempo perfeccionando. Si lo hubiéramos desarrollado nosotros mismos, era muy probable que la calidad empeorara precisamente en aspectos difíciles, como los caracteres CJK o la accesibilidad. Además, consideramos que la diferenciación del producto no estaba en el propio renderizador, sino en la tipografía y en una experiencia de uso propia de cada plataforma.
En cambio, nosotros decidimos cuándo crearlo
Crear la disposición del texto requiere tiempo y memoria. Los documentos grandes contienen decenas de miles de líneas, así que no podíamos crearlas todas.
Por eso solo creamos las líneas visibles en la pantalla y las que están alrededor. Y descartamos de inmediato las líneas que se alejan de la pantalla. Incluso después de desplazarse durante mucho tiempo por un documento de 1 MB, solo permanecen activas entre cuarenta y sesenta disposiciones.
Estimamos de antemano la altura de las líneas que todavía no hemos creado. Lo hacemos porque la barra de desplazamiento necesita conocer la longitud total del documento.
Por supuesto, a veces la estimación es incorrecta. Si la altura recién calculada difiere de la prevista, la pantalla puede desplazarse. En ese caso, corregimos la posición de desplazamiento en el mismo fotograma por una distancia equivalente a la diferencia. A ojos del usuario, no debería haber ocurrido nada.
Las líneas en las que se está componiendo hangul se dibujan sin adornos. Esto se debe a que, si durante la entrada se intercalan atributos como la negrita o la ocultación, la cantidad de caracteres que conoce el método de entrada puede diferir de la cantidad de caracteres que aparece en la pantalla.
El primer problema que encontramos fue el rostro de los caracteres chinos
Cuando se delega en la plataforma, también se heredan los valores predeterminados de la plataforma.
La fuente predeterminada de la interfaz de Ubuntu no contiene hangul. Por eso, la fuente que el sistema eligió como sustituta fue Noto Sans CJK JP. El hangul se veía bien, pero algunos caracteres chinos aparecían con formas japonesas. Esto se debe a que hay caracteres que, aun teniendo el mismo código Unicode, poseen formas diferentes en Corea y Japón.
La solución fue sencilla. Colocamos Noto Sans CJK KR al principio de la lista de fuentes de la interfaz.
Pero había algo aún más importante. Si nosotros no fijamos el criterio, la plataforma responde con sus propios valores predeterminados, no con el idioma del usuario.
Creamos formas adecuadas para cada idioma mediante el orden de las fuentes
La pila de fuentes busca los caracteres empezando por el principio. Solo los caracteres que no existen en la primera fuente pasan a la siguiente.
Aprovechando esta propiedad, podemos mostrar el texto latino con una fuente con serifas y el hangul con una fuente sin serifas. Con una sola línea de configuración combinamos fuentes apropiadas para cada idioma.
Si la fuente de lectura se deja vacía, se utiliza la fuente del cuerpo del texto tal cual. Si se especifica una fuente distinta, solo cambia en el modo de lectura. En el modo de código fuente usamos una fuente de código.
El tamaño de los caracteres sigue la configuración de accesibilidad del sistema operativo. Así, quienes hayan aumentado el tamaño del texto en el sistema no tienen que volver a configurarlo en cada aplicación.

El lector de pantalla también aprovecha la misma base. Como las funciones de accesibilidad ya están conectadas a la capa de texto de la plataforma, nosotros solo tenemos que transmitir con precisión el contenido de la línea solicitada.
Si falta una traducción, la compilación falla
Las frases de la interfaz se escriben en inglés y se utilizan como claves de la tabla de traducciones. Si no hay una traducción, la frase aparece en inglés tal cual en la pantalla.
El problema es que no se produce ningún error. Aunque falte una traducción, el inglés se mezcla silenciosamente con los demás idiomas.
Por eso creamos un script de comprobación. Recopila las frases que se utilizan realmente en el código y las compara con las tablas de traducción de 12 idiomas. Si una frase se añade en un solo idioma o se omite una traducción, la compilación falla.
Cada tabla de traducciones contiene 304 claves y en el código se utilizan realmente 282 frases. Los idiomas compatibles son English, 한국어, 日本語, 简体中文, 繁體中文, Deutsch, Français, Español, Português (Brasil), Русский, Italiano y Polski.

Cuando se cambia el idioma, abrimos una ventana nueva con el mismo documento y cerramos la anterior. Si tradujéramos uno por uno los cientos de widgets que ya están abiertos, habría muchas probabilidades de omitir alguno. Consideramos que era más seguro volver a abrir la ventana una vez en el momento de cambiar el idioma que mantener una ruta compleja que casi nunca se utiliza.
Cuando se delega en la plataforma, el resultado también se parece a la plataforma
Aunque se trate del mismo documento, los píxeles no son exactamente iguales en todos los sistemas operativos. Esto se debe a que cada uno utiliza métodos distintos para suavizar los caracteres y fuentes predeterminadas diferentes.
No intentamos que sean iguales a la fuerza. En su lugar, mantenemos iguales los criterios del documento, como la proporción del tamaño de los caracteres, la altura de línea y los márgenes.
El resultado de la sustitución también puede variar según las fuentes instaladas. Por eso, en lugar de prometer un resultado específico, mostramos de forma transparente el orden en el que solicitamos las fuentes. Y el usuario también puede cambiarlo directamente.
No dibujar directamente no significa que la responsabilidad desaparezca. Debemos decidir con mayor precisión qué delegar y en qué orden solicitarlo.