Suporte a OpenType Variable Fonts no Inkscape

Bibliotecas Pango e Harfbuzz

Duas das principais bibliotecas envolvidas nessa tarefa são Hafbuzz e Pango. O que segue abaixo é um relato da minha compreensão atual da relação entre essas duas bibliotecas. E, mais uma vez, é preciso alertar que eu posso estar enganado em alguns dos pontos apresentados abaixo! Mas vamos lá.

Uma parte da funcionalidade da biblioteca Pango está gradualmente sendo oferecida com maior qualidade pela biblioteca Harfbuzz, portanto é de se esperar que os projetos de software livre passem a usar Harfbuzz para tal, mas ainda há casos como o do Inkscape onde a bibliteca harfbuzz ainda não é utilizada.

A funcionalidade em questão se chama text-shaping e consiste em computar o posicionamento correto dos glifos em um trecho de texto. Existem scripts complexos como a escrita árabe que utilizam uma grande quantidade de ligaduras e regras de substituição contextual de glifos, por exemplo. Determinar quando e como são aplicadas essas
substituições é função dos algorítmos de shaping que são implementados pela biblioteca Harfbuzz.

Segue abaixo uma ilustração de glifos árabes exibidos separadamente e como eles mudam de forma quando são dispostos juntos em uma palavra:

Outros aspectos do árabe (e notem que eu não sei ler árabe, apenas conheço de forma bem superficial algumas das suas características tipográficas) são o fato de ser escrito da direita para a esquerda (chamamos de script RTL - “Right To Left”) e também a mudança de forma dos glifos para um mesmo caractere dependendo da posição em que se encontra numa palavra. Há diversas formas como a isolada ou as formas assumidas quando o caractere é empregado no início, no meio e no final de palavras, como ilustrado abaixo:

A biblioteca Pango também possui rotinas de shaping (invocadas pelo método pango_shape(…)), mas não são tão avançadas como as oferecidas pela biblioteca Harfbuzz (por meio do método hb_shape(…)).

Primeira estratégia: Migrar de Pango para Harfbuzz

Quando comecei a investigar o tema das fontes variáveis, tomei conhecimento dessas diferenças entre as bibliotecas (que são em grande parte desenvolvidas pelo mesmo programador, Behdad Esfahbod) e concluí que, independentemente da questão das fontes variáveis, havia já razões suficientes para modernizar o código de processamento de texto no Inkscape para usar a engine de shaping avançada da biblioteca Harfbuzz. Some-se a isso o fato da biblioteca Pango ainda não ter (até onde entendi por enquanto) conhecimento sobre as features de fontes variáveis da nova especificação OpenType 1.8.

Então resolvi investigar no código fonte do Inkscape onde exatamente o método pango_shape é invocado e como eu poderia alterá-lo para usar hb_shape em seu lugar. A resposta é que o método pango_shape é invocado em um único ponto, dentro da classe Layout::Calculator em http://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/15739/src/libnrtype/Layout-TNG-Compute.cpp#L1316

O que acontece aqui é relativamente complicado. Conforme explicado pelo próprio Behdad em um artigo de novembro de 2009, o motor de shaping tem como pré-requisito que o texto de entrada seja quebrado em trechos que façam uso de um único estilo de uma determinada fonte tipográfica. Sendo assim, a biblioteca Pango oferece um método chamado pango_itemize(…) que faz esse fatiamento do buffer de texto de entrada para que a aplicação posteriormente invoque o método de shaping para cada um dos trechos (chamados, em inglês, de items).

E a minha primeira surpresa foi descobrir que a biblioteca Harfbuzz não oferece um método “hb_itemize”. Harfbuzz se foca exclusivamente na etapa de shaping do texto e espera que outras bibliotecas ou códigos de aplicação se encarreguem da itemização. Com isso, conclui-se que a meta inicial de substituir por completo o uso da biblioteca Pango pela biblioteca Harfbuzz não é possível. Teremos que manter a Pango para executar a itemização (e provavelmente também algumas outras tarefas de layout de blocos de texto), e delegar apenas a etapa de shaping à Harfbuzz.

A outra descoberta que tive ao mesmo tempo foi ver que o código de renderização de texto do Inkscape é bastante extenso. Ele se concentra no subdiretório src/libnrtype/ e não sofreu grandes alterações ao longo da ultima década. Me lembro de ter lidado de leve com esse código por volta de 2008, quando fiz uma bolsa do programa Google Summer of Code em que minha meta era adicionar suporte a SVG Fonts no Inkscape. Meu mentor naquela época, Howard Hughes, também conhecido pelo nome de usuário cyreve, é autor de grande parte desse código. Talvez ele não tenha sido muito alterado na última década justamente pela sua complexidade, e também pelo receio de quebrar a compatibilidade com o padrão SVG. Eu acredito que o código como está hoje é muito sucetível a efeitos colaterais desastrosos se for alterado, pois é muito extenso e um pouco confuso de se ler. Julgo que um refactoring geral dessa base de código focada em legibilidade e corretude em relação ao padrão SVG seria extremamente benéfica.

Apenas o código do arquivo src/libnrtype/Layout-TNG-Compute.cpp sozinho tem um total de cerca de 2 mil linhas. Como eu me senti um pouco perdido (e exausto) lendo esse código todo na tela do computador, eu tomei a iniciativa de imprimí-lo em papel. Ter as 25 páginas de código fonte em mãos foi um pouco inibidor inicialmente, mas depois me deu muito mais coragem para ler e interpretar tudo e absorver o significado e o propósito de cada classe em uso.