1 pontos por GN⁺ 2024-05-20 | 1 comentários | Compartilhar no WhatsApp
  • 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 p alterna para o modo de edição
    • Depois de selecionar um ponto, é possível arrastá-lo para ajustar sua posição
    • A tecla enter imprime 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/d movem a imagem
    • As teclas r/e aumentam 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

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 de n fica baixo e o primeiro ponto de a fica alto, então a linha de conexão atravessa o a na diagonal e pode fazê-lo parecer um e
    • Em ti, o t termina logo acima da linha de base e o i começa na linha de base, criando uma crista pouco natural
  • 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 letra
    • 1: conecta-se a outra letra perto da linha de base
    • 2: conecta-se a outra letra logo acima da linha de base
    • 3: 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 a estiver no início da palavra, o ponto adicional fica estranho
    • Em um a depois de w, a linha pode atravessar o a de outro jeito
    • Quando t se conecta a k, sua forma pode se deformar
  • 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
  • A função de ajuste se comporta de maneira diferente para cada letra
    • A função de ajuste de q adiciona 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 n cria uma interrupção com 30% de probabilidade quando a próxima letra começa em 3, ou move o último ponto
  • Ao combinar os caminhos básicos de todas as letras, 1, 2 e 3 são ignorados; quando aparece 0, 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 Nonsense que 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

 
GN⁺ 2024-05-20
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

    • Parece um desafio! https://www.handwritingocr.com :)
    • Foi por isso que na faculdade eu precisei abandonar a letra cursiva de propósito
    • Comigo é a mesma coisa, e depois de algumas horas nem eu mesmo consigo decodificar
  • 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

    • Já existem até fontes para plotter
      Diferente das fontes que normalmente imaginamos, elas precisam ser trajetos para seguir, não contornos para preencher
    • Se as curvas já existem, isso parece bem fácil de fazer
      Só que pode ser entediante se tiver que ser manual, ou se você quiser fazer assim
    • Gosto muito da forma como isso mistura tecnologia e arte
  • 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

    • A frase “o essencial da letra cursiva é não tirar a caneta do papel” em si está correta, mas a interpretação é diferente
      Na cursiva, a ligação entre letras depende do contexto
      Por exemplo, a forma pode mudar por legibilidade dependendo se depois de b vem um a ou um o, e mesmo dentro de uma palavra pode haver casos em que você queira tirar a caneta entre letras
      Ainda 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
    • O ponto principal parece ser que cada par de letras se encaixa de um jeito diferente, e isso precisa ser tratado
    • Todo par de letras se conecta de uma forma diferente
      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 decimal
    Vejo uma função chamada adjust; não conheço bem a especificação de fontes, mas talvez desse para serializar 0,{x:12.2,y:13.2} de outro jeito, como 0,[12.2,13.2], e fazer a conversão na função adjust

    • Como qualquer outra habilidade, caligrafia também pode melhorar com um pouco de esforço