1 puntos por GN⁺ 2024-05-20 | 1 comentarios | Compartir por WhatsApp
  • Partiendo de un generador de alfabeto en letras de molde hecho en JavaScript, este es el proceso con el que dos meses después logró implementar en código incluso caligrafía cursiva a mano
  • Las letras se crean marcando coordenadas clave con la herramienta p5js, puliéndolas con curvas de Chaikin y convirtiéndolas luego en trayectorias de grosor variable
  • En la cursiva, la forma de conectar cambia según cada par de letras, así que se añaden etiquetas 0~3 al inicio y final de cada trayectoria para distinguir entre no conectable, línea base, sobre la línea base y cerca de la x-height
  • Al formar palabras, se elige una entre 2 o 3 trayectorias por letra y, según la altura de conexión de las letras vecinas, se agregan, eliminan o reemplazan puntos antes de sumar variación con Perlin noise
  • Tras la minificación, la clase de letras cursivas ocupa 26.1kb, más que los 9.7kb de las letras de molde, debido a las múltiples trayectorias y a las funciones de ajuste según letras vecinas

De la generación en letras de molde a la expansión hacia cursiva

  • El generador anterior de alfabeto en letras de molde definía en código los puntos clave de la trayectoria de cada letra
    • Se colocaban unos 10 puntos por letra
    • Se suavizaba la trayectoria con el algoritmo de curvas de Chaikin
    • La trayectoria se convertía en una forma cuyo grosor variaba a lo largo de su longitud
    • La forma final se dibujaba con p5js
  • En las letras de molde, las coordenadas se escribían directamente en el código, y había que ajustar los puntos manualmente hasta que la letra se viera natural
  • Para la implementación en cursiva, se creó una herramienta de diseño de letras aparte para reducir ese trabajo repetitivo

Herramienta para diseñar trayectorias de letras en p5js

  • Se creó y usó en el editor de p5js una herramienta para definir e imprimir puntos clave
  • La herramienta muestra tanto letras de ejemplo para dar escala y contexto como un área para diseñar una letra nueva
    • Al colocar con clic los puntos clave de una trayectoria, se muestra el resultado con la curva de Chaikin aplicada
    • La tecla p cambia al modo de edición
    • Tras seleccionar un punto, se puede arrastrar para ajustar su posición
    • La tecla enter imprime la trayectoria en la consola
  • Para cada letra se crearon 2 o 3 opciones, y la trayectoria resultante toma la forma de un arreglo de coordenadas {x, y}
  • Para tomar como referencia su propia letra, escribió a mano ejemplos en minúsculas y mayúsculas, cargó esas imágenes en la herramienta generadora y las calcó
    • Las teclas w/a/s/d mueven la imagen
    • r/e acercan o alejan la imagen
    • Los números escritos en el papel son coordenadas x/y para ajustar esa zona a la ventana de creación de letras

El problema de las conexiones en cursiva y las etiquetas 0~3

  • En algunos pares de letras, basta con unir la trayectoria de puntos clave de una letra con la de la siguiente y aplicar una sola vez la curva de Chaikin para lograr una conexión natural
  • Pero en algunas combinaciones, la línea de conexión arruina la forma de la letra
    • En na, el último punto de n queda bajo y el primer punto de a alto, así que la línea de conexión cruza a en diagonal y puede hacer que parezca una e
    • En ti, t termina justo sobre la línea base e i empieza en la línea base, lo que genera una cresta poco natural
  • En vez de escribir reglas para cada par específico de letras, se añade un número con información de altura de conexión al inicio y final de cada trayectoria
    • 0: no puede conectarse con otra letra
    • 1: se conecta con otra letra cerca de la línea base
    • 2: se conecta con otra letra justo por encima de la línea base
    • 3: se conecta con otra letra cerca de la x-height
  • Incluso con la misma letra, la forma de agregar o eliminar puntos cambia según si está al inicio de la palabra o según las letras anterior y siguiente
    • Si a está al inicio de una palabra, un punto adicional se ve extraño
    • En a después de w, la línea puede cruzar la a de otra manera
    • Si t se une con k, su forma puede alterarse
  • Se probaron todos los pares de letras y se creó variabilidad mediante varias opciones de trayectoria y ediciones según letras vecinas
  • Idealmente, se querría tener de 5 a 6 opciones de trayectoria por letra, pero hay que equilibrarlo con el tamaño del archivo

Procedimiento para generar palabras

  • Al formar una palabra, primero se elige para cada carácter una de sus 2 o 3 trayectorias base
  • La información de conexión de inicio y fin de la trayectoria elegida se transmite a las letras adyacentes
    • Incluso en una misma letra, la información del punto final puede variar según la opción de trayectoria elegida, así que primero hay que escoger todas las trayectorias de las letras
  • Después, la trayectoria base se ajusta para adaptarse a las letras vecinas
    • Si la altura final de la letra anterior es 2, se puede eliminar un punto inicial de la trayectoria actual
    • Si la altura inicial de la siguiente letra es 1, se puede agregar un punto en una posición específica
  • La función de ajuste actúa de forma distinta para cada letra
    • La función de ajuste de q agrega una ruptura al final con 70% de probabilidad, y reemplaza o añade puntos según la información final de la letra anterior o la inicial de la siguiente
    • La función de ajuste de n crea una ruptura con 30% de probabilidad o mueve el último punto cuando la siguiente letra empieza en 3
  • Al combinar todas las trayectorias base de las letras, 1, 2 y 3 se ignoran, y cuando aparece 0 se inicia una nueva trayectoria para crear una ruptura
  • A la trayectoria combinada se le aplica la curva de Chaikin, luego se convierte en una forma de grosor variable y finalmente se le añade una ligera oscilación con Perlin noise

Tamaño y forma de uso

  • La clase de letras de molde pesaba 9.7kb, y la clase de letras cursivas minificada pesa actualmente 26.1kb
  • La versión cursiva es más grande porque cada letra tiene varias trayectorias y además incluye funciones que ajustan puntos según las letras adyacentes
  • Aún quedan ideas para reducir más el tamaño
    • Actualmente las letras se diseñan tomando como base un tamaño de fuente 20 y luego se redimensionan
    • Por eso hay muchas coordenadas como x: 14.5
    • Si el tamaño base se cambiara a 200, se podrían usar valores como 145 y eliminar decimales para reducir cada letra
    • Ese cambio debe hacerse con cuidado, así que quedó en la lista de tareas pendientes
  • El uso principal de esta caligrafía es en títulos, etiquetas y notas garabateadas del diagrama en el que está trabajando
  • Usar trayectorias codificadas en lugar de una fuente permite manipular la trayectoria, por ejemplo cambiando directamente la posición de las letras o el grosor dentro de una letra individual
  • También se ofrece un print de Meaningful Nonsense hecho con una versión más desarrollada de este código de caligrafía, y cada impresión es un resultado único generado al hacer el pedido

1 comentarios

 
GN⁺ 2024-05-20
Comentarios de Hacker News
  • Si codifico mi letra a mano, parece que podría considerarse un hash unidireccional
    Si la leo después, no hay forma de descifrar qué demonios intentaba escribir

    • ¡Suena como un reto! https://www.handwritingocr.com :)
    • Por eso en la universidad tuve que abandonar a propósito la letra cursiva
    • A mí me pasa igual, y después de unas horas ni yo mismo la puedo descifrar
  • Está bastante bueno un video de YouTube de Stuff Made Here que trata algo parecido: https://www.youtube.com/watch?v=cQO2XTP7QDw
    Fue entretenido de ver porque también explica el proceso de prueba y error, y el repositorio de síntesis de escritura a mano también está interesante: https://github.com/sjvasquez/handwriting-synthesis

  • El artwork del final es bastante bonito
    Me pregunto si el siguiente paso será convertir esto en una fuente real para poder escribirla en cualquier programa

    • Ya existen fuentes para plotter
      A diferencia de las fuentes que solemos imaginar, no deben ser contornos para rellenar, sino trayectorias para seguir dibujando
    • Si ya tienes las curvas, debería ser bastante fácil
      Aunque si hay que hacerlo a mano, o si quieres hacerlo así, puede volverse aburrido
    • Me gusta mucho cómo aquí se mezclan tecnología y arte
  • No entendí muy bien la parte de que las conexiones entre letras no encajan
    Para mí, la esencia de la cursiva es no levantar el bolígrafo del papel, y por eso la manera de unir las letras ya está incluida en la propia escritura
    Parece que el autor en realidad no escribe así, y por eso surgió el problema
    Aun así, el resto del texto, donde lo resolvió como la forma más simple de dibujar varias letras en pantalla sin meterse con las fuentes, es muy interesante

    • La frase “la esencia de la cursiva es no levantar el bolígrafo del papel” en sí es correcta, pero la interpretación es distinta
      En cursiva, las conexiones entre letras dependen del contexto
      Por ejemplo, la b puede verse distinta según si después viene una a o una o, por legibilidad, y aun dentro de una palabra puede haber casos en los que quieras levantar el bolígrafo entre letras
      Aun así, eso no significa romper las “reglas” de la cursiva
      Puede que te lo hayan enseñado distinto y que esa enseñanza sea válida, pero no conozco un estilo de cursiva en el que las conexiones no deban depender del contexto
    • El punto parece ser que cada par de letras encaja de una manera distinta, y eso hay que resolverlo
    • Todos los pares de letras se conectan de manera diferente
      Igual que el kerning en fuentes que no van unidas, hay que codificar cómo se ven varias secuencias de letras
  • ¡Qué belleza! Ojalá hubiera más fuentes de escritura cursiva a mano
    Mi trabajo de hace 2 años está aquí: https://certik.github.io/slabikar-otf/

  • Está genial, pero ojalá mi letra fuera lo bastante buena como para querer convertirla en mi propia fuente :)
    Si cambias el tamaño base a 200 en lugar de < 14.5, podrías definir el punto como 145 y ahorrarte un carácter decimal
    Veo una función llamada adjust; no conozco bien la especificación de fuentes, pero quizá podrías serializar 0,{x:12.2,y:13.2} de otra manera, como 0,[12.2,13.2], y luego transformarlo dentro de la función adjust

    • Como con otras habilidades, la caligrafía también puede mejorar con un poco de esfuerzo