1 puntos por GN⁺ 2024-08-11 | 1 comentarios | Compartir por WhatsApp
  • Lanzado en diciembre de 2023, 175 Pixel Font Megapack es un proyecto de fuentes pixeladas que manejó la generación de fuentes, las pruebas de calidad y la distribución con una cadena de herramientas propia hecha en Rust
  • Los paquetes anteriores tenían 12 fuentes en 2016 y 40 en 2018, y el nuevo paquete comenzó con la meta de elevar al mismo tiempo la calidad, el estilo, el soporte de idiomas y la automatización de la distribución
  • Las nuevas fuentes superan la limitación de solo soportar ASCII y ahora admiten 176 caracteres latinos extendidos para EFIGS, pero se excluyeron los caracteres asiáticos y no latinos por temas de calidad y tiempo de producción
  • La herramienta en Rust pifo crea contornos de glifos, kerning automático, TTF, tilesheets y atlas de texturas empaquetados a partir de un tilesheet PNG y una configuración TOML, y puede procesar incluso 175 fuentes en pocos segundos
  • Las imágenes de muestra grandes, el kerning automático y los scripts de distribución con butler para itch.io redujeron la carga de revisión, corrección y subida manual, lo que permitió mejorar rápidamente la calidad de casi 200 fuentes

Del paquete anterior de fuentes pixeladas al Megapack

  • El primer paquete de fuentes de 2016 fue un conjunto de 12 fuentes creado cuando empezaba el trabajo en Ikenfell
    • Pulió las fuentes que estaba creando para el juego y añadió algunas más para venderlas en itch.io
    • Se usaron en varios juegos indie y tuvieron buena recepción
  • El segundo paquete de 2018 creció hasta 40 fuentes y también mejoró mucho en calidad
    • Creó tablas de kerning para mejorar el renderizado de oraciones
    • También ofreció formatos precompilados fáciles de usar en varios motores de juego
    • Lo promocionó mostrando sus fuentes aplicadas en capturas de pantalla de juegos de desarrolladores indie
  • Los paquetes anteriores se usaron en cientos de juegos indie y también en Cadence of Hyrule de Nintendo
    • Varias fuentes también se usaron en Get in the Car, Loser de Love Conquers All Games
  • Después del lanzamiento de Ikenfell, incluso durante un largo periodo de burnout, siguió mejorando sus habilidades en Rust y continuó trabajando en fuentes con la idea de crear algún día un nuevo paquete de fuentes pixeladas

Objetivos del Megapack

  • La meta inicial del nuevo paquete era llegar a 100 fuentes, pero el resultado final fue de 175 fuentes pixeladas
    • Los paquetes anteriores tenían 12 y 40 fuentes respectivamente
    • El nuevo paquete apuntaba a fuentes que pudieran usarse en géneros variados como ciencia ficción, fantasía, horror, granja y juegos cozy
  • La petición más frecuente y la mayor queja sobre los paquetes anteriores era que solo soportaban caracteres ASCII
    • El nuevo paquete adoptó un conjunto de caracteres latinos extendidos para soportar EFIGS, es decir, English, French, Italian, German y Spanish
    • El conjunto final de caracteres fue de 176
    • Los idiomas asiáticos o basados en alfabetos no latinos se excluyeron porque era difícil alcanzar la calidad deseada con conjuntos de caracteres menos familiares y porque el tiempo de producción aumentaba mucho
  • Como la UI de los juegos necesita jerarquía visual, la idea fue crear cada fuente no como un solo estilo sino como una familia tipográfica
    • Por ejemplo, la familia tipográfica Virtue incluye 20 estilos
    • Así, los desarrolladores pueden variar tamaño y grosor sin mezclar fuentes de estilos muy distintos
  • El kerning había sido uno de los mayores consumos de tiempo al crear los paquetes anteriores
    • Si hay 176 caracteres soportados, la cantidad posible de pares de kerning puede llegar hasta 176²
    • Para no ingresar manualmente todos los pares, se decidió calcular la mayoría automáticamente y ajustar a mano solo lo que el algoritmo no resolvía bien
  • El control de calidad y la distribución también se convirtieron en objetivos de automatización
    • Antes, después de corregir errores de píxeles o bugs de kerning, había que exportar de nuevo, probar y subir manualmente a itch.io
    • La nueva cadena de herramientas buscaba generar texto de muestra y visualizaciones de kerning para encontrar problemas rápido y verificar al instante los resultados de cada corrección

Preparación para mejorar la calidad del diseño tipográfico

  • Aunque tenía mucha experiencia en pixel art y en fuentes pixeladas, nunca había estudiado de forma seria el diseño tipográfico tradicional
  • Durante el trabajo consultó Design School: Type de Richard Poulin
    • Lo usó como un libro introductorio que le ayudó a aprender la terminología y las convenciones del diseño tipográfico
  • También reunió como referencia fotos de textos que veía a su alrededor
    • Le sirvieron letreros de tiendas pequeñas, museos, galerías, festivales, pósters de eventos locales y portadas de libros
    • No era para copiar tipografías, sino para estudiar formas de letras, descendentes y diferencias entre letras delgadas y anchas
  • Al observar fuentes decorativas en la calle, aprendió que muchas tipografías “llamativas” no adornan en exceso todas las letras, sino que concentran la decoración en las mayúsculas y tratan las minúsculas de forma más sutil

El papel de la herramienta Rust pifo

  • Para lograr estos objetivos escribió su propio programa en Rust, pifo
  • El diseño de las fuentes en sí se hacía con herramientas normales de pixel art
    • La entrada es un tilesheet PNG y un archivo TOML de configuración
    • Un comando de ejemplo tiene la forma pifo --all --output "Faraway" --input "Faraway*"
  • pifo recorta la imagen de entrada en tiles de glifos individuales, crea contornos de glifos, calcula automáticamente los pares de kerning y luego exporta archivos TTF
    • También genera otros formatos para usarlos directamente en varios motores
    • El trabajo sobre glifos individuales está paralelizado, así que una sola fuente se procesa casi al instante
    • Incluso procesando una por una las 175 fuentes, solo tarda unos segundos
  • Los principales crates de Rust usados fueron los siguientes
    • clap: parsing de argumentos de línea de comandos
    • image: decodificación y codificación de imágenes
    • rayon: paralelización
    • serde: serialización de datos
    • glyph-names: mapeo entre caracteres y nombres de glifos
    • ab-glyph: carga y rasterización de fuentes
    • crunch: empaquetado de rectángulos

Proceso de generación de contornos de glifos

  • Cada hoja de fuente consiste en un tilesheet y un archivo de configuración TOML
    • La configuración incluye version, baseline, line_gap, spacing, metrics, auto_kerning, auto_kerning_min, manual_kerning, skip_kerning_left, skip_kerning_right y otros
    • El tamaño de la cuadrícula puede variar, pero siempre debe ser uniforme y los caracteres deben estar en posiciones definidas
    • La herramienta solo procesa píxeles 100% blancos, y el fondo cuadriculado y la línea base se usan solo como guía
  • Un glifo TrueType está formado por uno o más contornos (contours)
    • En una fuente pixelada, hace falta crear un contorno por cada grupo de píxeles conectados, es decir, por cada clúster
    • Por ejemplo, si una t minúscula tiene dos bloques de píxeles separados, hacen falta dos contornos
  • La generación de contornos avanza por varias etapas
    • Toma solo los píxeles blancos de RgbaImage y los reúne en un HashSet de estructuras Point
    • Empieza en un píxel arbitrario y hace un flood fill sobre los píxeles adyacentes, repitiendo hasta que ya no queden píxeles sin visitar para encontrar los clústeres
    • En cada clúster recolecta como bordes expuestos las caras que no tienen píxeles adyacentes
    • Conecta la cabeza y la cola de esos bordes para formar caminos cerrados y convertirlos en contornos
  • Los clústeres con agujeros pueden generar varios contornos
    • El contorno exterior gira en sentido horario y los agujeros interiores en sentido antihorario
    • Esa diferencia de dirección coincide con la forma en que TTF representa los agujeros
  • Se eliminan los puntos intermedios sobre líneas rectas continuas
    • Es una optimización para reducir el tamaño del archivo y acelerar la rasterización

Automatización de la tabla de kerning

  • Además de los contornos, para crear un TTF también hace falta una tabla de kerning
    • La tabla de kerning desplaza ciertos pares de caracteres hacia la izquierda para que las palabras se vean más naturales
    • Por ejemplo, si los pares Va y lt se mueven 1 píxel a la izquierda, se ven mejor
  • El kerning manual se define en manual_kerning dentro del TOML
    • Se hace con una forma como { left = "V", right = "a", kern = -1 }
    • También se soporta la opción alts = true para no tener que especificar por separado todos los caracteres acentuados
    • Así se pueden mapear caracteres alternativos como àáâãäå para a y aplicarles el mismo kerning
  • El kerning automático se calcula moviendo el glifo derecho hacia la izquierda 1 píxel a la vez
    • Busca la posición más cercana en la que no toque al glifo izquierdo
    • Incluso el contacto por esquinas se considera contacto
    • En el ejemplo LV, es posible acercar V 1 píxel, pero con 2 píxeles los píxeles ya se tocan, así que el valor de kerning queda en -1
  • El cálculo automático del kerning respeta los valores definidos manualmente y la configuración de exclusiones
    • skip_kerning_left y skip_kerning_right permiten excluir glifos en una dirección concreta
    • Todos los pares de kerning se calculan en paralelo usando rayon

Formatos de exportación

  • PIFO genera no solo TTF, sino también tilesheets y atlas de texturas empaquetados
  • Un archivo TTF es un archivo binario compuesto por varias tablas
    • La herramienta de exportación llena las tablas head, hhea, maxp, OS/2, hmtx, cmap, loca, glyf, kern, name y post
    • Cada tabla debe registrar posición, longitud y checksum, y eso se maneja con begin_table() y end_table()
  • El tamaño base de las fuentes pixeladas se fijó en 16
    • Si se renderiza a tamaño 16, cada píxel queda exactamente en 1 px
    • Para escalar sin vibraciones, conviene dibujar en múltiplos de 16, como 32, 48 o 64
  • La exportación de tilesheets, a diferencia de la hoja de entrada, se ordena por codepoints Unicode
    • El archivo de datos que se genera junto con ellas incluye filas y columnas, tamaño de tile, línea base, interlineado, ancho del espacio, métricas de glifos y tabla de kerning
    • Se serializa en varios formatos como JSON, XML y TOML usando serde
  • También se generan atlas empaquetados
    • Se usa su propio crate de empaquetado de rectángulos crunch
    • Como al empaquetar de forma compacta se pierde la información de posición, para el renderizado se incluyen datos extra como x, y, w, h, off_x, off_y y adv

Pruebas de calidad e imágenes de muestra

  • Para alcanzar la calidad deseada, añadió a PIFO una función de generación de imágenes de muestra gigantes
  • Las imágenes de muestra están compuestas por varios bloques de prueba
  • Como podía generar al instante las imágenes de muestra durante el trabajo, logró encontrar y corregir problemas rápidamente
    • Ese proceso elevó el nivel general de calidad y acabado de casi 200 fuentes

Automatización de la distribución en itch.io

  • El resultado final fueron 175 fuentes pixeladas, y eligió itch.io como la tienda en línea para descarga que ya venía usando
  • La tarea más engorrosa fue crear un proyecto individual de itch para cada fuente
    • Ese trabajo solo fue necesario una vez por fuente
    • Después, las subidas y el mantenimiento se pudieron manejar con scripts de línea de comandos
  • El script de distribución consta de tres pasos
    • Compilar PIFO en modo release
    • Construir los recursos de las fuentes deseadas
    • Actualizar el proyecto de itch de cada fuente con los recursos nuevos
  • Un patrón de entrada como --input "Faraway*" encuentra estilos con el mismo prefijo, como Faraway - Regular y Faraway - Bold, y los agrupa en un solo paquete de familia tipográfica
  • Para la subida final usó la herramienta de distribución por línea de comandos butler que ofrece itch
    • La distribución se hace con una forma como butler push ../distro/faraway chevyray/pixel-font-faraway:assets
    • Como Butler rastrea los archivos modificados y actualiza solo lo necesario, no hizo falta implementar hashing de archivos ni un manejo de versiones especial

1 comentarios

 
GN⁺ 2024-08-11
Opiniones en Hacker News
  • Son fuentes geniales y el artículo también es interesante.
    Me quedé pensando que ojalá el juego falso de la parte superior derecha https://chevyray.dev/blog/creating-175-fonts/old_previews.pn... fuera un juego real.
    Me gusta porque tiene una vibra tipo “Wonder Boy in Monster World para GBA”.
    Eso sí, viendo la licencia, parece que no permite usar los TTF en proyectos de software open source, así que hay que tenerlo en cuenta.
    No soy abogado, pero la última cláusula se lee como una prohibición clara: https://github.com/ChevyRay/pixel_font_megapack_license/blob...

    • Si te gustan los juegos de plataformas, conviene probar Celeste.
      La escena de ese mockup toma como referencia la escena inicial de Celeste.
    • Está claro que no se puede distribuir la fuente en sí como open source o bajo algo tipo CC, pero no es tan claro que eso prohíba incluirla y distribuirla junto con software cuyas demás partes sí son open source.
      La intención parece ser claramente que se use en juegos en etapa de producto final, donde el open source es relativamente menos común, más que en motores de juego o plantillas.
      Al leer este artículo también me vino a la mente otro caso límite de copyright: en Estados Unidos, las tipografías (typefaces) no están protegidas por copyright.
      Las fuentes sí están protegidas como programas de computadora, pero las tipografías y las fuentes bitmap simples no.
      Así que este flujo de trabajo básicamente toma una tilesheet original sin copyright, crea un TTF con copyright y luego vuelve otra vez a una tilesheet/atlas de salida sin copyright.
    • Debí haber escrito en proyectos de software open source, no “en software open source”.
  • Realmente impresionante.
    Crear un set completo de fuentes puede tomar fácilmente un año.
    Hay que crear todos los glifos de la 'A' a la 'Z', mayúsculas y minúsculas, paréntesis, ampersand, signos de exclamación y demás, y si es posible también variantes como negrita e itálica.
    Sin esas variantes, la utilidad de la fuente queda limitada.
    Lo que realmente marca la diferencia es el kerning, es decir, el espaciado entre letras, y uno puede obsesionarse con eso sin fin.
    En el texto principal también dice que, si se admiten 176 caracteres, habría que ingresar hasta 176² = 37,976 pares de kerning, así que decidió crear sus propias herramientas para semiautomatizar la mayor parte y solo ingresar manualmente lo que el algoritmo no cubría bien.

    • Eso es cuando limitas la fuente a un uso puramente en inglés.
      Para admitir otros idiomas, incluso lenguas que usan el alfabeto latino como francés, español, italiano o portugués, hacen falta caracteres adicionales.
      Después quizá quieras admitir también griego, cirílico, japonés y chino.
      Por ejemplo, según Wikipedia, “las fuentes Noto admiten más de 77,000 caracteres, lo que equivale a aproximadamente la mitad de los 149,186 caracteres definidos en Unicode 15.0”.
    • Un set completo de fuentes puede tomar fácilmente un año, pero crear una familia tipográfica puede convertirse en un proyecto de toda la vida.
    • Para ser sincero, no me convence eso de que “un set completo de fuentes fácilmente toma un año”.
      Uno puede obsesionarse infinitamente con cualquier cosa.
      También parece que áreas como los idiomas, la escritura, la música y la caligrafía atraen mucho a personas con tendencia a obsesionarse.
      El punto es que este tipo de comentarios suena a poner barreras de entrada.
      Las cosas que pueden desanimar a alguien que quiere entrar a un campo nuevo siempre me suenan algo delicadas.
  • Muy bueno.
    Una cosa que me da curiosidad es por qué eligió este subconjunto de caracteres especiales escandinavos.
    El sueco usa äöå, y el noruego/danés usan æøå, pero esta fuente tiene æ y no ø.
    Entonces, si se quitara æ, seguiría manteniendo soporte para sueco, y si se agregara ø, también podría soportar noruego y danés.
    Me pregunto si fue una omisión simple o si existe algún locale que use æ pero no ø.
    Como referencia, no estoy confundiendo æ con la ligadura œ, que es un glifo separado usado en francés.

    • El islandés usa ö en lugar de ø, pero al mismo tiempo también necesita ð e ý, que no están en esta fuente.
      De todos modos, Æ también se usa en textos antiguos en inglés como “encyclopædia” o en plurales de palabras provenientes del latín: https://en.wiktionary.org/wiki/Category:English_plurals_in_-...
    • Fue simplemente una omisión.
      De hecho, recién bastante avanzado el proyecto me di cuenta de que a mi set de caracteres le faltaba ø.
      Sin duda es posible volver a agregarlo a todas las fuentes y parchearlas, pero estaba esperando para ver si había suficiente demanda como para justificar ese trabajo.
      Aun así, poder admitir dos idiomas más suena bastante genial.
  • También me gustaron algunas de las fuentes usadas en el sitio y el estilo sencillo.
    Por suerte, está publicado en un artículo aparte: https://chevyray.dev/blog/how-this-site-is-made/#catppuccin-...

  • Interesante.
    Antes no sabía que al codificar fuentes pixeladas como TTF se convierten a vectores.
    Para quien las cargue en un renderizador de texto adecuado, eso también permitiría cierto escalado fluido.
    Claro que los motores de juegos que usan fuentes pixeladas casi siempre en proporción 1:1 pueden ser la excepción.

    • Hacerlo así permite usarlas también en editores gráficos tradicionales como Photoshop, InDesign, Affinity o Aseprite.
      Esas herramientas no tienen el concepto de fuente pixelada, así que si usas un TTF con hinting y antialiasing desactivados, se pueden aprovechar en esas apps.
  • Genial
    También me gusta que este trabajo le haya ayudado económicamente a quien lo hizo.
    Recuerdo el nombre Chevy Ray del mundo de los juegos indie, pero no se me viene a la mente exactamente qué hizo.
    Creo que era algo más o menos de la corriente de VVVVVV, Nidhogg o Canabalt, alrededor de 2010–2012.

    • Era Flashpunk.
      Beacon también era excelente — me trae recuerdos; extraño los juegos indie.
    • Probablemente el juego del que hablas sea Beacon.
    • Ikenfell
    • También disfruté muchísimo Ikenfell.
    • ¿Flashpunk?
  • Excelente
    Al ver a una persona renacentista como el autor de este artículo, recuerdo una época en la que artistas e ingenieros no estaban claramente separados, sino que eran una sola cosa.

    • Entonces te recomiendo leer bien sobre da Vinci.
      No artículos tipo “Top 10 inventos de da Vinci”.
      En realidad había una distinción bastante grande entre ambas cosas.
      Yo también puedo modelar en Maya una nave espacial para llegar a Alpha Centauri con una dinámica sospechosa y no verificada.
      Pero eso está muy lejos de construirla de verdad y enviarla al espacio interestelar.
      Los dibujos son bonitos e imaginativos, eso sí.
  • En Rust es sorprendentemente fácil hacer que este tipo de trabajo se ejecute en varios núcleos.
    Puede bastar con insertar una sola llamada en una cadena de funciones.

    • Rust está diseñado desde el principio para ofrecer seguridad de memoria y seguridad de hilos.
      Suponiendo que sigas las reglas que define el lenguaje, el multithreading es casi “gratis”.
      La ley de Amdahl sigue influyendo, pero al menos la app no explota frente a tus ojos.
    • No es algo exclusivo de Rust.
      Scala y Java también soportan esto de forma nativa.
  • Un trabajo realmente excelente, y el artículo también es bueno.
    Con algunos trucos, muchos de los algoritmos podrían hacerse más rápidos.
    Por lo que leí, una pista podría ser cambiar los hash maps usados para dibujar caracteres y mapear variantes ASCII por bitmaps y arreglos de índices de bytes.
    Claro que, como ya es lo suficientemente rápido, en este código no importa demasiado.

    • Me alegra que menciones esto; es totalmente cierto.
      El sitio no incluye todo el código, pero en realidad se asignan y clonan bastantes strings y estructuras de datos.
      Usé código óptimo en los lugares obvios, y partes como copiar bitmaps o las tareas fáciles de paralelizar eran tan rápidas que terminaban al instante, así que ni siquiera intenté optimizar las demás partes.
      Aun así, se podría hacer.
      Es fácil olvidar lo rápidos que son los lenguajes cercanos al bajo nivel como Rust, C++ y Go, y más aún cuando se les suman herramientas básicas de multithreading y colas de trabajo.
  • Quienes estén interesados en las fuentes deberían revisar también https://tomorrow.type.today/
    Es un estudio de tipografía que crea fuentes excelentes, originales y experimentales.
    Una persona de nuestro equipo está muy metida en la tipografía, así que está armando una colección de sus trabajos en https://play.soot.com/tomorrowtypetoday.

    • Como referencia, esa empresa está registrada en Rusia.