Gerando a Elementar 2 como fonte variável

06 Maio 2021

Um relato sobre como a Elementar foi implementada como uma fonte variável, iluminando os principais obstáculos ao longo do percurso e as soluções empregadas para superá-los.

Considerações iniciais sobre fontes variáveis

1. Fontes variáveis permitem que o usuário interpole instâncias em qualquer localização dentro de um espaço de variação predefinido. A fonte variável é gerada a partir de múltiplas fontes mestras compatíveis.

2. O formato de fonte variável fornece um mecanismo para introduzir descontinuidades locais no espaço de variação. Isso permite que um glifo possa ser substituído por outro dependendo da localização, de forma análoga a um trem trocando de trilhos. O exemplo típico é o glifo do dólar, no qual duas barras verticais podem se fundir em uma só nos pesos mais escuros.

3. Fontes variáveis possuem hoje amplo suporte em APIs e interfaces. Por exemplo, em CSS é possível especificar os parâmetros de uma fonte variável com o atributo font-variation-settings, e no DrawBot com o comando fontVariations(). Diversos programas de design e ferramentas de teste oferecem uma interface para controlar os parâmetros de uma fonte variável com sliders e/ou input numérico.

Encaixando a Elementar no formato variável

A Elementar 2 usa o formato de fonte variável de um jeito bastante particular:

A. Os desenhos de letra baseados em bitmaps são descontínuos e incompatíveis entre as fontes mestras, portanto a interpolação entre os glifos é contornada quase que completamente – ela é usada apenas para controlar o tamanho e a proporção dos elementos.

B. As variações são obtidas através do (ab)uso do mecanismo de substituição de glifos (2), que é empregado para trocar todo o conjunto de glifos a cada nova localização mestra no espaço de variação. As fontes mestras precisam ser compatíveis, o que significa que cada fonte mestra precisa conter todos os glifos de todas as outras fontes mestras. Esse é o principal gargalo no processo de geração da fonte, fazendo com que o tempo de execução aumente exponencialmente na medida em que novos glifos e novas fontes mestras vão sendo adicionados.

C. O formato de fonte variável é usado principalmente como mecanismo de transferência e seleção para fontes mestras descontínuas, aproveitando a integração ‘nativa’ do formato de fonte variável em APIs e intefaces modernas (3). Os eixos largura de elemento e altura de elemento são os únicos eixos de variação ‘verdadeiros’ no sentido convencional, empregando interpolação ao invés substituição de glifos.

Primeiro protótipo (Junho 2020)

O primeiro protóripo da ‘Elementar Variável’ foi construído como um experimento de fim-de-semana. Eu já havia convertido alguns dos meus outros tipos em fontes variáveis, e estava curioso pra descobrir se a Elementar também poderia ser encaixada no formato.

Neste estágio eu estava gerando fontes variáveis com o método descrito na documentação do RoboFont, usando a extensão Batch. Eu consegui gerar uma pequena fonte de teste contendo apenas alguns glifos e apenas um subconjunto dos eixos de variação (altura, largura e tamanho do elemento). Também criei uma página de teste em HTML/CSS/JS para poder visualizar a fonte variável de forma interativa usando sliders. Fiquei positivamente surpreso com o desempenho da fonte variável, em comparação à implementação anterior na qual cada estilo era uma fonte individual. O uso de uma fonte variável também tornou a implementação da interface mais fácil.

Tendo provado para mim mesmo que poderia ser feito, e tendo coisas mais importantes em que trabalhar na época, deixei o projeto em suspenso até conseguir retomá-lo novamente em Março de 2021.

Adicionando mais eixos e glifos

Com a geração de fonte variável e a página de teste automatizados, eu comecei a acrescentar os eixos que faltavam (espessura de traço vertical, espessura de traço horizontal, estilo) e mais glifos. Isso fez com que o número de glifos em cada fonte mestra crescesse muito rapidamente, e a geração das fontes ficou impraticavelmente lenta – algo em torno de mais de uma hora para uma fonte contendo apenas a caixa baixa (a-z).1 Estava claro que esta abordagem não poderia ser ampliada até uma fonte completa, e eu comecei a buscar meios de tornar a geração de fontes variáveis mais rápida.

Otimizando a geração de fonte variável

Entre as fontes mestras no formato UFO e a fonte variável compilada está uma uma série de etapas de preparação para moldar o conteúdo da fonte ao formato exigido. Ao final da linha de produção está o módulo fontTools.varlib, que usa um arquivo .designspace e um conjunto de fontes mestras TTF com compatibilidade estrita. A extensão Batch cuida das etapas de preparação intermediárias:

  • adicionar pontos de controle aos segmentos retos para tornar glifos mestres compatíveis
  • decompor glifos misturados (que contém tanto contornos quanto componentes)
  • converter contornos cúbicos em quadráticos
  • tornar o kerning das fontes mestras compatível
  • gerar fontes mestras em formato TTF a partir de UFOs

A extensão Batch também pode ser usada sem a interface, executando o gerador de fontes variáveis diretamente através de um script em Python:

from variableFontGenerator import BatchDesignSpaceProcessor
p = BatchDesignSpaceProcessor()
p.read('myfont.designspace')
p.generateVariationFont('myfont.ttf')

A esta altura eu já havia plugado essa função nas minhas próprias ferramentas, adicionando alguns passos para reduzir o conjunto de glifos das fontes UFO, construir o arquivo .designspace automaticamente, etc. Tive que dar um passo atrás e examinar o conteúdo da função generateVariationFont em busca de oportunidades para otimização.

Por exemplo, como a Elementar não é uma fonte variável típica baseada em interpolação, todos os passos de otimização dos contornos não eram necessários. Eu também podia desenhar o glifos do elemento2 diretamente como uma curva quadrática, e assim não precisaria mais converter toda a fonte cúbica em quadrática. Eu acabei escrevendo a minha própria versão da função de geração de fontes variáveis do Batch, e consegui reduzir consideravelmente o tempo de geração de fonte. Isso tudo ainda estava rodando dentro do RoboFont.

Outro ganho de velocidade foi conquistado gerando-se as fontes TTF mestras usando o ufo2ft diretamente, ao invés de usando o AFDKO através da função font.generate(). Após essa mudança, toda a linha de geração da fonte podia ser executada fora do RoboFont – assim eu posso continuar desenhando, enquando a fonte é gerada em um processo de fundo.

Fatiando o espaço de variação em múltiplas fontes

Finalmente, para reduzir ainda mais a contagem de glifos nas fontes mestras, resolvi dividir a fonte variável única contendo todos os eixos de variação em diversas fontes menores contendo apenas os eixos de altura, largura, largura do elemento e altura do elemento. Como as fontes mestras são descontínuas, isso pode ser feito sem introduzir uma ‘quebra’ visível nas transições. A interface precisou ser ajustada de acordo: ao invés de conectar os sliders diretamente aos valores do atributo font-variation-settings, agora também é preciso trocar o atributo font-family quando os parâmetros de estilo, espessura de traço vertical ou espessura de traço horizontal são alterados.

Com fontes menores para gerar, todo o processo ficou muito mais ágil e mais divertido, e eu posso voltar ao trabalho de acrescentar mais glifos.


Notas

  1. Vale a pena mencionar que este trabalho está sendo feito em um MacBook Air de 2012. Máquinas mais novas provavelmente podem executar o mesmo código em menos tempo. 

  2. O glifo do elemento é o único contorno nas fontes – todos os outros glifos são construídos com componentes do elemento.