Mais opções de fontes variáveis para a fonte da IU do sistema macOS no Chromium 83

O Catalina traz uma nova fonte de sistema variável unificada para o macOS.

A seção "system-ui" da especificação do Módulo de fontes CSS Nível 4 define uma palavra-chave de fonte system-ui que permite aos desenvolvedores usar a fonte padrão do sistema operacional integrada, turbo-otimizada, localizada, de qualidade mega-alta e sem necessidade de download diretamente nos sites e apps.

body {
  font-family: system-ui;
}

Essa escolha de tipografia é semelhante a dizer "use a fonte padrão do sistema para a localidade atual deste usuário".

No macOS, a fonte system-ui é a San Francisco, que foi avaliada, testada e… atualizada recentemente por uma equipe de design. Primeiro, vamos falar sobre os novos recursos interessantes de fontes variáveis no Catalina. Depois, vamos abordar alguns bugs e como os engenheiros do Chromium os resolveram.

Neste post, presumimos que você já conhece as fontes variáveis. Caso contrário, confira Introdução às fontes variáveis na Web e o vídeo abaixo.

Compatibilidade com navegadores

No momento da redação deste artigo, o system-ui tem suporte do Chromium (desde a versão 56), do Edge (desde a versão 79), do Safari (desde a versão 11) e do Firefox (desde a versão 43), mas com a palavra-chave -apple-system. Consulte Posso usar fontes variáveis? para atualizações.

Novos poderes

As novas funcionalidades que o Catalina trouxe para a fonte do sistema agora estão disponíveis para desenvolvedores da Web a partir do Chromium 83. A fonte system-ui agora tem mais configurações variáveis: dimensionamento óptico e dois ajustes de peso exclusivos:

Mojave
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}
Catalina
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

No Mojave, system-ui é uma fonte variável com apenas configurações de wght. Enquanto system-ui no Catalina é uma fonte variável com configurações de wght, opsz, GRAD e YAXS.

Parece que há algumas oportunidades interessantes de design de melhoria progressiva! Se quiser, analise as sutilezas da fonte do sistema.

wght

Aceita uma espessura de fonte entre 0 e 900 e é aplicada igualmente a todos os caracteres.

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

O dimensionamento óptico é semelhante ao kerning ou ao espaçamento entre letras, mas o espaçamento é feito por um olho humano em vez de matemática. Um valor de 19 ou menos é destinado ao espaçamento de texto e corpo do texto, enquanto 20 ou mais é para espaçamento de cabeçalhos e títulos de exibição.

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

Semelhante à espessura, mas sem afetar o espaçamento horizontal. Ele aceita valores entre 400 e 1000.

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

Estica o glifo verticalmente. Ele aceita valores entre 400 e 1000.

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

Combinando as opções

Com algumas linhas de CSS, podemos ajustar as configurações de fonte para um negrito de nossa escolha ou testar outras combinações interessantes:

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

E assim, os usuários do Chromium no macOS veem seu peso 750 personalizado e atualizado com alguns outros ajustes divertidos 👍

O macOS 10.15 adicionou novos recursos à fonte do sistema, e no macOS 10.15 um bug complicado do system-ui foi registrado no rastreador de bugs do Chromium. Será que eles são parentes?

Apêndice: a regressão system-ui

Esta história começa com um bug diferente: #1005969. Isso foi denunciado no macOS 10.15 porque o espaçamento da fonte system-ui parecia estreito e apertado.

Comparação de dois parágrafos de uma página de grupo do Facebook. À esquerda está o Chrome e à direita o Safari. O Chrome é sutil, mas tem um espaçamento um pouco menor.
Chrome à esquerda (rastreamento mais preciso), Safari à direita (melhor espaçamento óptico)

Contexto

Você já notou no macOS 10.14 como seus parágrafos ou cabeçalhos "encaixavam" em uma fonte de aparência diferente quando o tamanho aumentava ou diminuía?

No Mojave (macOS 10.14), a fonte system-ui alternava entre duas fontes dependendo do tamanho da fonte de destino. Quando o texto estava em 20px, o macOS usava "San Francisco Text". Quando o texto tinha 20px ou mais, o macOS usava "San Francisco Display". O dimensionamento óptico foi criado de forma estática em duas fontes separadas.

O Catalina (macOS 10.15) lançou uma nova fonte variável unificada para São Francisco. Não é mais necessário gerenciar "Texto" e "Display". Ele também ganhou a nova configuração de variação opsz descrita anteriormente.

h1 {
  font-variation-settings: 'opsz' 20;
}

Infelizmente, o valor padrão opsz na nova fonte Catalina é 20, e os engenheiros do Chromium não estavam preparados para aplicar opsz à fonte do sistema. Isso fez com que tamanhos menores fossem exibidos muito estreitos.

Para corrigir isso, o Chromium precisava aplicar opsz corretamente à fonte do sistema. Isso levou à correção do problema nº 1005969. Você venceu! Ou foi…?

Ainda não foi concluído

Foi aí que ficou complicado: o Chromium aplicou opsz, mas algo ainda não parecia certo. As fontes do sistema no Mac têm uma tabela de fontes adicional chamada trak, que ajusta o espaçamento horizontal. Enquanto trabalhavam na correção, os engenheiros do Chromium perceberam que, no macOS, ao recuperar métricas horizontais de um objeto CTFontRef, as métricas trak já estavam sendo incluídas nos resultados. A biblioteca de formatação do Chromium HarfBuzz precisa de métricas em que os valores trak ainda não foram incluídos.

Uma exibição da interface do sistema e de todas as variações e espessuras de fonte em uma lista. Metade deles não tem diferenças de peso aplicadas.
Esquerda: espessuras em negrito aplicadas aos tamanhos de fonte 19 e menores. Certo: tamanhos de fonte 20 e maiores perdem o estilo em negrito

Internamente, o Skia (a biblioteca de gráficos, não a família tipográfica de mesmo nome) usa a classe CGFontRef de CoreGraphics e a classe CTFontRef de CoreText. Devido às conversões internas necessárias entre esses objetos (usados para manter a compatibilidade com versões anteriores e acessar as APIs necessárias em ambas as classes), o Skia perderia informações de peso em determinadas circunstâncias, e as fontes em negrito parariam de funcionar. Esse problema foi rastreado em Issue #1057654.

A Skia ainda precisa ser compatível com o macOS 10.11 porque o Chromium ainda oferece suporte a ele. No 10.11, as fontes "San Francisco Text" e "San Francisco Display" não eram variáveis. Em vez disso, cada uma era uma família de fontes separadas para cada peso disponível. Em algum momento, os IDs de glifos ficaram dessincronizados. Portanto, se o Skia fizesse o ajuste de texto (convertendo texto em glifos que podem ser desenhados) com "San Francisco Text", ele ficaria sem sentido se fosse desenhado com "San Francisco Display", e vice-versa. Mesmo que o Skia peça um tamanho diferente, o macOS pode mudar para o outro. É possível sempre usar uma das fontes e apenas dimensioná-la (usando uma matriz para aumentar em vez de pedir um tamanho maior), mas o CoreText tem um problema em que não dimensiona glifos sbix (emoji colorido) para cima, apenas para baixo. É um pouco mais complexo do que isso. CoreText parece limitar a extensão vertical após a aplicação da matriz, o que parece estar relacionado à incapacidade de desenhar emojis em ângulos de 45 graus. De qualquer forma, se você quiser que o emoji apareça grande, faça uma cópia da fonte para ter uma versão maior.

Para criar cópias de objetos CTFont em tamanhos diferentes internamente e garantir que os mesmos dados de fonte sejam usados, o Chromium extraiu o CGFont do CTFont e criou um novo CTFont com o CGFont. Os objetos CGFont são independentes de tamanho, e a troca mágica acontece no nível CoreText. Isso funcionou bem até a versão 10.154. Em 10.15, essa viagem de ida e volta acabou perdendo muitas informações, resultando no problema de peso. O Flutter percebeu o problema de peso, e uma correção alternativa para redimensionamento foi feita para criar o novo CTFont diretamente do CTFont original, controlando o tamanho óptico diretamente usando um atributo antigo, mas não documentado, em CoreText. Isso mantém as coisas funcionando no 10.11 e corrige outros problemas, como definir explicitamente o tamanho óptico como o valor padrão.

No entanto, isso preserva mais da "magia" CoreText na fonte. Uma delas parece ser que ele ainda ajusta os avanços de glifos de alguma forma diferente da tabela trak (cuja aplicação o Chromium já estava tentando suprimir com outro atributo não documentado).

O CGFont não faz nada disso, então talvez o Chromium possa tirar o CGFont do CTFont e usar apenas para receber avanços? Infelizmente, isso não funcionaria porque CoreText também interfere nas fontes de outras maneiras. Por exemplo, ele aumenta um pouco o tamanho de emojis pequenos. O CGFont não sabe disso, então você acabaria com emojis baseados em sbix muito próximos uns dos outros, já que você estaria medindo em um tamanho, mas o CoreText os desenharia maiores em alguma quantidade. O Chromium quer os avanços do CTFont, mas sem rastreamento e, de preferência, sem mais nada.

Como a correção do problema de espaçamento exigiu um conjunto de correções interconectadas do Blink e do Skia, os engenheiros do Chromium não puderam "apenas reverter" para corrigir o problema. Os engenheiros do Chromium também tentaram usar uma flag de build diferente para mudar um codepath relacionado a fontes no Skia, o que corrigiu o problema das fontes em negrito, mas piorou o problema de espaçamento.

A correção

No fim, é claro que o Chromium queria corrigir as duas coisas. Agora, o Chromium usa as funções de métricas de fontes OpenType integradas do HarfBuzz para recuperar métricas horizontais diretamente dos dados binários nas tabelas de fontes da fonte do sistema. Com isso, o Chromium evita CoreText e Skia quando a fonte tem uma tabela trak, exceto quando é a fonte de emoji.

Uma exibição da interface do sistema e de todas as variações e espessuras de fonte em uma lista. A metade que não estava funcionando antes agora está ótima.

Enquanto isso, ainda há o problema 10123 do Skia (em inglês) para acompanhar a correção completa no Skia e voltar a usar o Skia para recuperar as métricas de fontes do sistema de lá, em vez da correção atual que passa pelo HarfBuzz.