Por que deixamos a renderização dos caracteres a cargo da plataforma em vez de desenhá-los diretamente
Você já percebeu que o hangul parece normal, mas somente os caracteres chineses parecem um pouco estranhos? Quando decidimos não desenhar os caracteres diretamente e deixar essa tarefa a cargo do mecanismo de texto da plataforma, nosso trabalho deixa de ser \"o que desenhar\" e passa a ser \"qual fonte pedir\".

Muitas coisas precisam acontecer até que o texto apareça na tela. É preciso transformar caracteres em formas, dividir as linhas e desenhá-los em pixels. Também é necessário lidar com tudo, desde a composição do hangul até caracteres chineses, emojis, escrita árabe e fallback de fontes.
Nós não recriamos esse processo. Deixamos essa tarefa a cargo do Pango e do HarfBuzz no Linux, do DirectWrite no Windows e do TextKit 2 no macOS.
Isso porque é uma área que os sistemas operacionais vêm aprimorando há muito tempo. Se nós mesmos a implementássemos, havia uma grande possibilidade de a qualidade piorar justamente nas partes mais difíceis, como caracteres CJK e acessibilidade. Também entendemos que o diferencial do produto não estava no renderizador em si, mas na tipografia e em uma experiência de uso que parecesse nativa da plataforma.
Em vez disso, nós decidimos quando criar
O layout de texto consome tempo e memória para ser criado. Documentos grandes têm dezenas de milhares de linhas, então não era possível criar todas elas.
Por isso, criamos apenas as linhas visíveis na tela e as que ficam ao redor delas. As linhas que se afastam da tela são descartadas imediatamente. Mesmo depois de rolar por muito tempo um documento de 1 MB, apenas cerca de quarenta a sessenta layouts permanecem ativos.
Estimamos previamente a altura das linhas que ainda não foram criadas. Isso é necessário porque a barra de rolagem precisa conhecer o comprimento total do documento.
Naturalmente, às vezes a estimativa está errada. Se a altura recém-calculada for diferente da esperada, o conteúdo da tela pode se deslocar. Nesse caso, corrigimos a posição da rolagem pela diferença no mesmo quadro. Aos olhos do usuário, deve parecer que nada aconteceu.
As linhas em que o hangul está sendo composto são renderizadas sem formatação. Isso ocorre porque, se atributos como negrito ou oculto forem aplicados durante a digitação, a quantidade de caracteres reconhecida pelo método de entrada poderá ficar diferente da quantidade exibida na tela.
O primeiro problema que encontramos foi a aparência dos caracteres chineses
Quando deixamos algo a cargo da plataforma, também herdamos seus valores padrão.
A fonte padrão da interface do Ubuntu não contém hangul. Por isso, a fonte escolhida pelo sistema como substituta era a Noto Sans CJK JP. O hangul era exibido corretamente, mas alguns caracteres chineses apareciam com formas japonesas. Isso acontece porque há caracteres que, embora tenham o mesmo código Unicode, possuem formas diferentes na Coreia e no Japão.
A solução foi simples. Colocamos a Noto Sans CJK KR antes das demais na lista de fontes da interface.
Mas havia algo ainda mais importante. Se nós não definirmos o critério, a plataforma responderá com base nos próprios valores padrão, e não no idioma do usuário.
Criamos formas adequadas para cada idioma por meio da ordem das fontes
A pilha de fontes procura os caracteres começando pela primeira fonte. Somente os caracteres que não existem nela passam para a fonte seguinte.
Aproveitando esse comportamento, podemos exibir o alfabeto latino em uma fonte serifada e o hangul em uma fonte sem serifa. Uma única linha de configuração permite combinar fontes adequadas a cada idioma.
Quando a fonte de leitura fica em branco, usamos a fonte do corpo do texto sem alterações. Se uma fonte diferente for especificada, ela será aplicada somente no modo de leitura. No modo de código-fonte, usamos a fonte de código.
O tamanho dos caracteres acompanha as configurações de acessibilidade do sistema operacional. Assim, quem aumentou o tamanho do texto no sistema não precisa configurá-lo novamente em cada aplicativo.

O leitor de tela também aproveita a mesma base. Como os recursos de acessibilidade já estão conectados à camada de texto da plataforma, basta fornecermos corretamente o conteúdo da linha solicitada.
Se faltar uma tradução, a compilação falha
As frases da interface são escritas em inglês e usadas como chaves na tabela de traduções. Quando não há tradução, a frase em inglês aparece na tela sem alterações.
O problema é que isso não gera um erro. Mesmo quando falta uma tradução, o inglês simplesmente aparece misturado ao restante do conteúdo.
Por isso, criamos um script de verificação. Ele reúne as frases realmente usadas no código e as compara com as tabelas de tradução de 12 idiomas. Se uma frase for adicionada a apenas um idioma ou se alguma tradução for esquecida, a compilação falha.
Cada tabela de traduções tem 304 chaves, e 282 frases são realmente usadas no código. Os idiomas disponíveis são English, 한국어, 日本語, 简体中文, 繁體中文, Deutsch, Français, Español, Português (Brasil), Русский, Italiano e Polski.

Quando o idioma é alterado, abrimos uma nova janela com o mesmo documento e fechamos a janela existente. Se traduzíssemos um por um as centenas de widgets que já estão abertos, haveria uma grande possibilidade de deixarmos algum de fora. Concluímos que é mais seguro reabrir a janela uma única vez no momento da troca de idioma do que manter um fluxo complexo que quase nunca é usado.
Quando deixamos a tarefa a cargo da plataforma, o resultado também se parece com ela
Mesmo com o mesmo documento, os pixels não são exatamente iguais em todos os sistemas operacionais. Isso acontece porque cada um suaviza os caracteres de uma maneira diferente e usa fontes padrão diferentes.
Não tentamos forçar resultados idênticos. Em vez disso, mantemos os mesmos critérios do documento, como a proporção do tamanho dos caracteres, a altura da linha e as margens.
Os resultados do fallback também podem variar de acordo com as fontes instaladas. Por isso, em vez de prometer um resultado específico, mostramos de maneira transparente a ordem em que as fontes são solicitadas. O usuário também pode alterá-la diretamente.
Não desenhar diretamente não significa que a responsabilidade desaparece. É preciso definir com ainda mais precisão o que será delegado e em que ordem cada recurso será solicitado.