A técnica de programar minha própria caligrafia
(amygoodchild.com)- O processo começou com um gerador de alfabeto em letras de forma em JavaScript e, dois meses depois, chegou à implementação de caligrafia cursiva manuscrita em código
- As letras são criadas marcando coordenadas essenciais com uma ferramenta em p5js, suavizadas com curvas de Chaikin e depois convertidas em caminhos de espessura variável
- Na cursiva, cada par de letras tem uma forma diferente de conexão; por isso, foram adicionadas tags de 0 a 3 no início e no fim dos caminhos para distinguir estados como sem conexão, linha de base, acima da linha de base e perto da x-height
- Ao formar uma palavra, escolhe-se um entre 2 ou 3 caminhos por letra; depois, pontos são adicionados, removidos ou substituídos conforme a altura de conexão das letras vizinhas, e uma oscilação é acrescentada com Perlin noise
- Após minificação, a classe de letras cursivas tem 26,1 kb, maior que os 9,7 kb das letras de forma, devido aos vários caminhos e às funções de correção para letras vizinhas
Da geração de letras de forma à expansão para cursiva
- O gerador anterior de alfabeto em letras de forma definia em código os pontos essenciais do caminho de cada letra
- Cerca de 10 pontos eram posicionados por letra
- O algoritmo de curvas de Chaikin suavizava o caminho
- O caminho era convertido para um formato cuja espessura variava ao longo do comprimento
- O p5js desenhava a forma final
- Nas letras de forma, era preciso escrever as coordenadas diretamente no código e ajustar manualmente os pontos até que a letra parecesse natural
- Na implementação da cursiva, foi criada uma ferramenta de desenho de letras separada para reduzir esse trabalho repetitivo
Ferramenta para desenhar caminhos de letras no p5js
- No editor do p5js, foi criada e usada uma ferramenta para definir e imprimir pontos essenciais
- A ferramenta oferece, ao mesmo tempo, letras de exemplo que mostram escala e contexto e uma área para desenhar uma nova letra
- Ao posicionar os pontos essenciais do caminho com cliques, o resultado com a curva de Chaikin aplicada é exibido
- A tecla
palterna para o modo de edição - Depois de selecionar um ponto, é possível arrastá-lo para ajustar sua posição
- A tecla
enterimprime o caminho no console
- Para cada letra, foram criadas 2 a 3 opções, e o caminho resultante fica no formato de um array de coordenadas
{x, y} - Para usar a própria caligrafia como referência, exemplos de letras minúsculas e maiúsculas foram escritos à mão, e essa imagem foi carregada na ferramenta de geração de letras para ser traçada por cima
- As teclas
w/a/s/dmovem a imagem - As teclas
r/eaumentam ou reduzem a imagem - Os números escritos no papel são as coordenadas x/y usadas para alinhar aquela área à janela de geração de letras
- As teclas
O problema das conexões na cursiva e as tags 0–3
- Alguns pares de letras se conectam naturalmente apenas anexando o caminho de pontos essenciais da próxima letra ao fim do caminho da letra anterior e aplicando a curva de Chaikin uma única vez
- Mas, em algumas combinações, a linha de conexão deforma a letra
- Em
na, o último ponto denfica baixo e o primeiro ponto deafica alto, então a linha de conexão atravessa oana diagonal e pode fazê-lo parecer ume - Em
ti, ottermina logo acima da linha de base e oicomeça na linha de base, criando uma crista pouco natural
- Em
- Em vez de escrever regras específicas para cada par de letras, informações de altura de conexão foram anexadas como números ao início e ao fim de cada caminho
0: não pode se conectar a outra letra1: conecta-se a outra letra perto da linha de base2: conecta-se a outra letra logo acima da linha de base3: conecta-se a outra letra perto da x-height
- Mesmo a mesma letra muda a forma de adicionar ou remover pontos dependendo de estar no início da palavra ou das letras antes e depois dela
- Se
aestiver no início da palavra, o ponto adicional fica estranho - Em um
adepois dew, a linha pode atravessar oade outro jeito - Quando
tse conecta ak, sua forma pode se deformar
- Se
- Todos os pares de letras foram testados, e a variabilidade foi criada com várias opções de caminhos e edições específicas para letras vizinhas
- Idealmente, cada letra teria 5 ou 6 opções de caminhos, mas isso precisa ser equilibrado com o tamanho do arquivo
Procedimento de geração de palavras
- Ao criar uma palavra, primeiro é escolhida, para cada caractere, uma das 2 a 3 rotas básicas
- As informações de conexão do início e do fim do caminho selecionado são passadas às letras adjacentes
- Mesmo para a mesma letra, as informações do ponto final podem variar conforme a opção de caminho escolhida; por isso, é preciso escolher primeiro todos os caminhos das letras
- Depois, o caminho básico é ajustado de acordo com as letras vizinhas
- Se a altura final da letra anterior for
2, é possível remover um ponto inicial do caminho atual - Se a altura inicial da próxima letra for
1, é possível adicionar um ponto em uma posição específica
- Se a altura final da letra anterior for
- A função de ajuste se comporta de maneira diferente para cada letra
- A função de ajuste de
qadiciona uma interrupção no final com 70% de probabilidade e substitui ou adiciona pontos conforme as informações do fim da letra anterior ou do início da próxima - A função de ajuste de
ncria uma interrupção com 30% de probabilidade quando a próxima letra começa em3, ou move o último ponto
- A função de ajuste de
- Ao combinar os caminhos básicos de todas as letras,
1,2e3são ignorados; quando aparece0, um novo caminho é iniciado, criando uma interrupção - A curva de Chaikin é aplicada ao caminho combinado; ele é convertido para uma forma de espessura variável e, em seguida, uma leve oscilação é adicionada com Perlin noise
Tamanho e forma de uso
- A classe de letras para letras de forma tinha 9,7 kb, enquanto a classe de letras cursivas minificada atualmente tem 26,1 kb
- A cursiva é maior porque há vários caminhos para cada letra e funções que ajustam pontos de acordo com letras adjacentes
- Ainda há ideias para economizar mais espaço
- Atualmente, as letras são desenhadas com base em um tamanho de fonte padrão de 20 e depois redimensionadas
- Por isso, há muitas coordenadas como
x: 14.5 - Se o tamanho base for alterado para 200, seria possível eliminar casas decimais, como em
145, reduzindo um caractere - Essa mudança precisa ser feita com cuidado, então está na lista de tarefas futuras
- O principal uso dessa caligrafia é em títulos, rótulos e anotações rabiscadas dos diagramas em desenvolvimento
- Usar caminhos codificados em vez de uma fonte permite manipular os caminhos diretamente, alterando, por exemplo, a posição das letras ou a espessura dentro de letras individuais
- Também estão disponíveis prints de
Meaningful Nonsenseque usam uma versão mais avançada desse código de caligrafia; cada print é um resultado único gerado no momento do pedido
1 comentários
Comentários do Hacker News
Se eu codificasse minha caligrafia, acho que ela poderia ser vista como um hash de mão única
Se eu for ler depois, não há como decifrar o que eu estava tentando escrever
Há um vídeo bem legal no YouTube do Stuff Made Here que trata de algo parecido: https://www.youtube.com/watch?v=cQO2XTP7QDw
Foi divertido de assistir porque ele também explica as tentativas e erros, e o repositório de síntese de caligrafia também é interessante: https://github.com/sjvasquez/handwriting-synthesis
A arte final no fim ficou bem bonita
Fico curioso se o próximo passo seria transformar isso em uma fonte de verdade, para que desse para digitar em qualquer programa
Diferente das fontes que normalmente imaginamos, elas precisam ser trajetos para seguir, não contornos para preencher
Só que pode ser entediante se tiver que ser manual, ou se você quiser fazer assim
Não entendi muito bem a parte sobre as conexões entre letras não encaixarem
Para mim, o essencial da letra cursiva é não tirar a caneta do papel, e por isso a maneira de ligar as letras já está incluída no próprio ato de escrever
Parece que o autor teve esse problema porque na prática não escreve assim
Ainda assim, o resto do texto é muito interessante por resolver isso da forma mais simples possível para desenhar várias letras na tela sem mexer em fontes
Na cursiva, a ligação entre letras depende do contexto
Por exemplo, a forma pode mudar por legibilidade dependendo se depois de
bvem umaou umo, e mesmo dentro de uma palavra pode haver casos em que você queira tirar a caneta entre letrasAinda assim, isso não significa quebrar as “regras” da cursiva
Você pode ter aprendido de outro jeito, e esse ensino pode até estar certo, mas não conheço um estilo de cursiva em que a ligação não deva depender do contexto
Assim como o kerning em fontes que não são conectadas, é preciso codificar como várias sequências de letras vão parecer
Lindo! Eu queria que existissem mais fontes de caligrafia cursiva
Aqui está um trabalho meu de 2 anos atrás: https://certik.github.io/slabikar-otf/
É legal, mas eu queria que minha letra fosse boa o bastante para eu querer transformá-la na minha própria fonte :)
Em vez de
< 14.5, se você mudar o tamanho padrão para 200, poderá definir o ponto como 145 e economizar um caractere decimalVejo uma função chamada
adjust; não conheço bem a especificação de fontes, mas talvez desse para serializar0,{x:12.2,y:13.2}de outro jeito, como0,[12.2,13.2], e fazer a conversão na funçãoadjust