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

Catalina traz uma nova fonte de sistema de variáveis unidas para o macOS.

Dominik Röttsches
Dominik Röttsches

A seção'system-ui' da especificação CSS Fonts Module nível 4 define uma palavra-chave de fonte system-ui que permite aos desenvolvedores usar a fonte padrão do sistema operacional integrada, otimizada para turbo, localizada, mega-alta e sem necessidade de download, diretamente nos sites e aplicativos.

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 é San Francisco, uma fonte que uma equipe de design analisou, testou e... atualizou recentemente. Primeiro, vamos abordar os novos recursos interessantes de fontes de variáveis na Catalina e depois alguns bugs e como os engenheiros do Chromium os resolveram.

Nesta postagem, pressupomos que você já tenha familiaridade com fontes variáveis. Caso contrário, assista a Introdução a fontes variáveis na Web e no vídeo abaixo.

Compatibilidade com navegadores

Até o momento, system-ui oferece suporte ao Chromium (a partir da versão 56), ao Edge (a partir da 79), ao Safari (a partir da 11) e ao Firefox (a partir da versão 43), mas com a palavra-chave -apple-system. Consulte Posso usar fontes variáveis? para conferir as atualizações.

Novos poderes

As novas habilidades que Catalina trouxe para a fonte do sistema estão disponíveis para desenvolvedores da Web a partir do Chromium 83. A fonte system-ui agora tem mais configurações variáveis: tamanho ó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. Já a system-ui na Catalina é uma fonte variável com as configurações wght, opsz, GRAD e YAXS.

Parece que tenho algumas ótimas oportunidades de design de aprimoramento progressivo para mim! 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 um cálculo matemático. Um valor de 19 ou menor serve para espaçamento entre o texto e o corpo do texto, enquanto 20 ou mais é para o espaçamento de cabeçalhos e títulos de exibição.

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

GRAD

Semelhante ao peso, mas sem tocar no espaçamento horizontal. Ela aceita valores entre 400 e 1000.

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

YAXS

Alonga o glifo verticalmente. Ela aceita valores entre 400 e 1000.

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

Como combinar as opções

Com algumas linhas de CSS, podemos ajustar as configurações de fonte para deixá-las em negrito ou testar outras combinações interessantes:

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

Assim, os usuários do Chromium no macOS verão seu peso de 750 personalizado atualizado com alguns outros ajustes divertidos 👍

Playground

Clique em Remix to Edit no Glitch abaixo para acessar uma cópia editável do Glitch e depois edite as novas opções font-variation-settings para ver como isso afeta a fonte. O Glitch só funcionará se você estiver usando um dispositivo macOS Catalina.

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. Quer saber se eles são relacionados?

Apêndice: a regressão system-ui

Essa história começa com um bug diferente: #1005969. Isso foi relatado em relação ao macOS 10.15 porque o espaçamento de fonte system-ui parecia estreito e apertado.

Uma comparação de dois parágrafos de uma página de grupo do Facebook. O Chrome está à esquerda e à direita o Safari. O Chrome é sutil, mas um pouco mais restrito em termos de espaçamento.
Chrome à esquerda (rastreamento mais rígido), Safari à direita (melhor espaçamento óptico)

Contexto

No macOS 10.14, você já percebeu que parágrafos ou cabeçalhos são "encaixados" em uma fonte de aparência diferente quando o tamanho aumenta ou diminui?

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

Catalina (macOS 10.15) enviou uma nova fonte de variável united para São Francisco. Chega de 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 de opsz na nova fonte Catalina é 20, e os engenheiros do Chromium não estavam preparados para aplicar opsz à fonte do sistema. Isso fazia com que os tamanhos menores fossem exibidos muito estreitos.

Para corrigir isso, o Chromium precisava aplicar opsz corretamente à fonte do sistema. Isso fez com que o problema 1005969 fosse corrigido. Vitória! Ou foi...?

Ainda não concluído

O problema ficou complicado: o Chromium aplicou opsz, mas algo ainda não apareceu. As fontes do sistema no Mac têm uma tabela de fontes extra 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 consideradas nos resultados. A biblioteca de modelagem do Chromium HarfBuzz precisa de métricas em que os valores trak ainda não foram considerados.

Exibição da IU do sistema e de toda a espessura da fonte e variações em uma lista. Metade deles não tem diferenças de peso aplicadas.
Esquerda: pesos em negrito aplicados a tamanhos de fonte 19 ou inferiores. Direita: fontes de tamanho 20 ou mais perdem o estilo em negrito.

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

O Skia ainda precisa oferecer suporte ao macOS 10.11 porque o Chromium ainda é compatível. Na versão 10.11, as fontes "San Francisco Text" e "San Francisco Display" não eram nem fontes 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 glifo ficaram dessincronizados. Portanto, se Skia definiu o texto (convertendo texto em glifos que podem ser desenhados) com "San Francisco Text", o texto ficaria sem sentido se desenhado com "San Francisco Display", e vice-versa. Mesmo que o Skia tenha solicitado um tamanho diferente, o macOS poderá alternar para o outro. É possível sempre usar uma das fontes e apenas dimensioná-la (usando uma matriz para aumentar em vez de solicitar um tamanho maior), mas CoreText tem um problema em que ele não dimensiona os glifos do sbix (Emoji de cor) para cima (apenas para baixo). É um pouco mais complexo do que isso. Na verdade, a CoreText parece limitar a extensão vertical após a aplicação da matriz, o que parece estar relacionado à impossibilidade de desenhar emojis em ângulos de 45 graus. Em qualquer caso, se você quiser que seu emoji seja mostrado em tamanho grande, terá que fazer uma cópia da fonte para obter uma versão grande.

Portanto, 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 da CTFont e criou um novo CTFont do CGFont. Os objetos CGFont são independentes de tamanho, e a alternância mágica acontece no nível do CoreText. Isso funcionou bem até 10.154. Nas 10h15, essa viagem de ida e volta acabou perdendo informações demais, resultando no problema de peso. O Flutter percebeu o problema de peso. Uma correção alternativa de 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 o funcionamento na versão 10.11 e corrige outros problemas, como definir explicitamente o tamanho óptico com o valor padrão.

No entanto, isso preserva mais da "mágica" do CoreText na fonte. Um deles parece ser que ele ainda ajusta os avanços de glifo de alguma forma diferente de apenas a tabela trak (o aplicativo do qual o Chromium já estava tentando suprimir por meio de outro atributo não documentado).

O CGFont não faz nada dessa "mágica", então talvez o Chromium possa obter o CGFont de desconto no CTFont e usá-lo para avançar? Infelizmente, isso não funcionaria porque o CoreText também afeta fontes de outras maneiras. Por exemplo, um emoji pequeno fica um pouco maior do que você pediu (aumentando um pouco o tamanho). O CGFont não sabe sobre isso, então seu emoji (baseado em sbix) ficaria muito perto um do outro, porque você estaria medindo em um tamanho, mas o CoreText mostraria um pouco maior. O Chromium quer que o CTFont avance, mas os quer sem rastreamento e, de preferência, sem qualquer outro problema.

Como a correção do problema de espaçamento exigia um conjunto de correções interconectadas do Blink e do Skia, os engenheiros do Chromium não podiam "simplesmente reverter" para corrigir o problema. Os engenheiros do Chromium também tentaram usar uma sinalização de versão diferente para alterar um caminho de código relacionado a fontes no Skia, o que corrigiu o problema de fontes em negrito, mas regressou o problema de espaçamento.

A correção

No final, é claro que o Chromium queria corrigir as duas coisas. O Chromium agora recorre ao uso de funções de métricas de fonte OpenType de fonte incorporada do HarfBuzz para recuperar métricas horizontais diretamente dos dados binários nas tabelas de fontes do sistema. Com isso, o Chromium está se desviando de CoreText e Skia quando a fonte tem uma tabela trak (exceto quando é a fonte de emojis).

Exibição da IU do sistema e de toda a espessura da fonte e variações em uma lista. A metade que não estava funcionando está boa agora.

Enquanto isso, ainda há o problema 10123 do Skia (link em inglês) para rastrear a correção completa desse problema no Skia e voltar a usar o Skia para recuperar as métricas de fonte do sistema a partir dele, em vez da correção atual que ocorre no HarfBuzz.