1 points par GN⁺ 2024-08-11 | 1 commentaires | Partager sur WhatsApp
  • Lancé en décembre 2023, le 175 Pixel Font Megapack est un projet de polices pixel qui gère la génération des polices, les tests qualité et le déploiement grâce à une toolchain Rust maison
  • Les packs précédents comptaient 12 polices en 2016 puis 40 en 2018 ; le nouveau pack a été lancé avec l’objectif d’améliorer d’un coup la qualité, le style, la prise en charge des langues et l’automatisation du déploiement
  • Les nouvelles polices dépassent la limite du support ASCII seul et prennent en charge 176 caractères latins étendus pour l’EFIGS, mais les langues asiatiques et les écritures non latines ont été exclues pour des raisons de qualité et de temps de production
  • L’outil Rust pifo génère, à partir de tilesheets PNG et d’une configuration TOML, les contours des glyphes, le kerning automatique, des TTF, des tilesheets et des atlas de textures packés, et traite même 175 polices en quelques secondes
  • De grandes images d’échantillons, le kerning automatique et des scripts de déploiement butler pour itch.io ont réduit la charge de vérification manuelle, de correction et d’upload, ce qui a permis d’améliorer rapidement la qualité de près de 200 polices

Du précédent pack de polices pixel au Megapack

  • Le premier pack de polices de 2016 était un ensemble de 12 polices créé au moment où commençait le travail sur Ikenfell
    • Des polices conçues pour le jeu ont été peaufinées, quelques autres ont été ajoutées, puis le tout a été vendu sur itch.io
    • Elles ont été utilisées dans plusieurs jeux indépendants et ont reçu un bon accueil
  • Le deuxième pack, en 2018, est passé à 40 polices et la qualité a nettement progressé
    • Des tables de kerning ont été créées pour améliorer le rendu des phrases
    • Des formats précompilés faciles à utiliser dans plusieurs moteurs de jeu ont aussi été fournis
    • La promotion s’est faite en montrant ses polices appliquées à des captures d’écran de jeux d’autres développeurs indépendants
  • Les précédents packs ont été utilisés dans des centaines de jeux indépendants, ainsi que dans Cadence of Hyrule de Nintendo
    • Plusieurs polices ont aussi été utilisées dans Get in the Car, Loser de Love Conquers All Games
  • Après la sortie de Ikenfell, malgré une longue période de burnout, l’auteur a continué à progresser en Rust et à travailler sur les polices en vue de créer un jour un nouveau pack de polices pixel

Les objectifs du Megapack

  • L’objectif initial du nouveau pack était de 100 polices, mais le résultat final atteint 175 polices pixel
    • Les packs précédents en comptaient respectivement 12 et 40
    • Le nouveau pack vise des polices utilisables dans des genres variés comme la SF, la fantasy, l’horreur, les jeux de ferme ou les jeux cosy
  • La demande et la critique les plus fréquentes à propos des anciens packs concernaient le support limité à l’ASCII
    • Le nouveau pack adopte un jeu de caractères latins étendus afin de prendre en charge l’EFIGS, c’est-à-dire English, French, Italian, German et Spanish
    • Le jeu de caractères final compte 176 caractères
    • Les langues asiatiques et les langues à base d’écritures non latines ont été exclues, car il est difficile d’atteindre le niveau de qualité souhaité avec des systèmes d’écriture moins familiers, et cela allongerait fortement le temps de production
  • Les interfaces de jeu ont besoin d’une hiérarchie visuelle, d’où la volonté de créer chaque police non pas comme un style unique mais comme une famille de polices
    • Par exemple, la famille de polices Virtue comprend 20 styles
    • Les développeurs peuvent ainsi varier taille et graisse sans mélanger des polices d’ambiances différentes
  • Le kerning était un gros poste de consommation de temps dans la création des packs précédents
    • Avec 176 caractères pris en charge, le nombre de paires de kerning possibles peut monter jusqu’à 176²
    • Plutôt que de saisir manuellement toutes les paires, la plupart sont calculées automatiquement et seules les insuffisances de l’algorithme sont complétées à la main
  • Le contrôle qualité et le déploiement ont aussi été automatisés
    • Auparavant, après correction d’un bug de pixel ou de kerning, il fallait réexporter, retester et reuploader manuellement sur itch.io
    • La nouvelle toolchain vise à générer du texte d’exemple et des visualisations de kerning pour repérer rapidement les problèmes et vérifier immédiatement le résultat des corrections

Préparer une meilleure qualité de design typographique

  • Même avec une grande expérience en pixel art et en polices pixel, l’auteur n’avait jamais étudié sérieusement le design typographique traditionnel
  • Pendant le travail, il s’est appuyé sur Design School: Type de Richard Poulin
    • Le livre a servi d’introduction pour apprendre la terminologie et les conventions du design typographique
  • Des photos de textes vues dans l’environnement quotidien ont également été rassemblées comme références
    • Enseignes de petites boutiques, musées, galeries, festivals, affiches d’événements locaux, couvertures de livres, etc. ont servi de matériau de référence
    • L’objectif n’était pas de copier des polices, mais d’étudier les formes des lettres, les lettres qui descendent sous la ligne de base, et les différences entre lettres fines et larges
  • En observant des polices décoratives vues à l’extérieur, l’auteur a appris que beaucoup de polices “ornementales” concentrent les décorations sur les majuscules et gardent des minuscules plus subtiles au lieu de surcharger chaque lettre

Le rôle de l’outil Rust pifo

  • Pour atteindre ces objectifs, l’auteur a écrit son propre programme Rust pifo
  • Le design des polices lui-même a été réalisé avec des outils classiques de pixel art
    • Les entrées sont une tilesheet PNG et un fichier TOML de configuration
    • Un exemple de commande est pifo --all --output "Faraway" --input "Faraway*"
  • pifo découpe les images d’entrée en tuiles de glyphes individuelles, génère les contours des glyphes, calcule automatiquement les paires de kerning puis exporte des fichiers TTF
    • D’autres formats sont également générés pour un usage immédiat dans plusieurs moteurs
    • Le traitement des glyphes individuels est parallélisé, si bien qu’une police seule est traitée presque instantanément
    • Même en traitant les 175 polices une par une, cela ne prend que quelques secondes
  • Les principaux crates Rust utilisés sont les suivants
    • clap : parsing des arguments en ligne de commande
    • image : décodage et encodage d’images
    • rayon : parallélisation
    • serde : sérialisation des données
    • glyph-names : mapping entre caractères et noms de glyphes
    • ab-glyph : chargement et rastérisation de polices
    • crunch : rectangle packing

Processus de génération des contours de glyphes

  • Chaque feuille de police se compose d’une tilesheet et d’un fichier de configuration TOML
    • La configuration inclut version, baseline, line_gap, spacing, metrics, auto_kerning, auto_kerning_min, manual_kerning, skip_kerning_left, skip_kerning_right, etc.
    • La taille de la grille peut varier, mais la grille doit toujours être uniforme, et les caractères doivent se trouver à des positions prédéfinies
    • L’outil ne traite que les pixels 100 % blancs ; le fond à damier et la ligne de base ne servent que de guides
  • Un glyphe TrueType se compose d’un ou plusieurs contours
    • Dans une police pixel, il faut créer un contour pour chaque groupe de pixels connecté, c’est-à-dire chaque cluster
    • Par exemple, si la lettre minuscule t comporte deux amas de pixels séparés, il faut deux contours
  • La génération des contours se déroule en plusieurs étapes
    • Les pixels blancs sont extraits de RgbaImage et rassemblés dans un HashSet de structures Point
    • On part d’un pixel arbitraire, puis on effectue un flood fill sur les pixels adjacents, en répétant jusqu’à ce qu’il ne reste plus de pixels non visités, afin d’identifier les clusters
    • Pour chaque cluster, on collecte les bords exposés correspondant aux faces sans pixel adjacent
    • Les têtes et queues des bords sont reliées pour former un chemin fermé, ensuite converti en contour
  • Un cluster avec des trous peut produire plusieurs contours
    • Le contour extérieur s’enroule dans le sens horaire, tandis que les trous intérieurs s’enroulent dans le sens antihoraire
    • Cette différence d’orientation correspond à la manière dont les trous sont représentés dans un TTF
  • Les points intermédiaires situés sur une même ligne droite continue sont supprimés
    • C’est une optimisation destinée à réduire la taille des fichiers et à accélérer la rastérisation

Automatisation de la table de kerning

  • Après les contours, l’autre élément indispensable pour produire un TTF est la table de kerning
    • Elle permet de rapprocher certains couples de caractères vers la gauche afin de rendre les mots plus naturels visuellement
    • Par exemple, tirer les paires Va ou lt d’un pixel vers la gauche améliore le rendu
  • Le kerning manuel est défini dans manual_kerning du TOML
    • Sous une forme comme { left = "V", right = "a", kern = -1 }
    • L’option alts = true est prise en charge pour éviter de déclarer séparément tous les caractères accentués
    • Elle mappe des caractères alternatifs comme àáâãäå pour a, afin d’appliquer le même kerning
  • Le kerning automatique est calculé en déplaçant le glyphe de droite d’un pixel à la fois vers la gauche
    • L’outil cherche la position la plus proche sans contact avec le glyphe de gauche
    • Le contact par les coins est lui aussi considéré comme un contact
    • Dans l’exemple LV, on peut rapprocher V d’un pixel, mais pas de deux, car les pixels se toucheraient ; la valeur de kerning est donc -1
  • Le calcul automatique du kerning respecte les valeurs manuelles et les réglages d’exclusion
    • skip_kerning_left et skip_kerning_right permettent d’exclure certains glyphes dans une direction donnée
    • rayon est utilisé pour calculer toutes les paires de kerning en parallèle

Formats d’export

  • PIFO génère non seulement des TTF, mais aussi des tilesheets et des atlas de textures packés
  • Un fichier TTF est un fichier binaire composé de plusieurs tables
    • L’outil d’export remplit les tables head, hhea, maxp, OS/2, hmtx, cmap, loca, glyf, kern, name, post
    • Chaque table doit enregistrer sa position, sa longueur et son checksum, ce qui est géré avec begin_table() et end_table()
  • La taille de base des polices pixel a été fixée à 16
    • En rendant la police à la taille 16, chaque pixel devient exactement 1 px
    • Pour agrandir sans tremblement, il faut dessiner en multiples de 16, comme 32, 48, 64
  • L’export des tilesheets, contrairement à la feuille d’entrée, est trié selon l’ordre des codepoints Unicode
    • Le fichier de données généré en parallèle contient les lignes et colonnes, la taille des tuiles, la ligne de base, l’interligne, la largeur de l’espace, les métriques de glyphes et la table de kerning
    • serde permet une sérialisation en plusieurs formats comme JSON, XML ou TOML
  • Des atlas packés sont également générés
    • Ils utilisent le crate maison de rectangle packing crunch
    • Comme un packing serré fait perdre l’information de position, des données supplémentaires comme x, y, w, h, off_x, off_y, adv sont incluses pour le rendu

Tests qualité et images d’échantillon

  • Pour atteindre le niveau de qualité visé, une fonction de génération d’images d’échantillon géantes a été ajoutée à PIFO
  • Les images d’échantillon se composent de plusieurs blocs de test
  • Comme ces images pouvaient être générées immédiatement pendant le travail, il a été possible de repérer et corriger rapidement les problèmes
    • Ce processus a permis d’élever la qualité globale et le niveau de finition de près de 200 polices

Automatisation du déploiement sur itch.io

  • Le résultat final était 175 polices pixel, et l’auteur a choisi itch.io comme boutique en ligne de téléchargement, déjà utilisée auparavant
  • La tâche la plus fastidieuse consistait à créer un projet itch séparé pour chaque police
    • Cette opération n’était nécessaire qu’une seule fois par police
    • Ensuite, les uploads et la maintenance pouvaient être gérés avec des scripts en ligne de commande
  • Le script de déploiement se compose de trois étapes
    • Compiler PIFO en mode release
    • Construire les assets des polices souhaitées
    • Mettre à jour chaque projet itch de police avec les nouveaux assets
  • Un motif d’entrée comme --input "Faraway*" permet de trouver les styles partageant le même préfixe, comme Faraway - Regular et Faraway - Bold, puis de les regrouper dans un seul package de famille de polices
  • Pour l’upload final, l’auteur utilise l’outil de déploiement en ligne de commande butler fourni par itch
    • Le déploiement se fait sous une forme comme butler push ../distro/faraway chevyray/pixel-font-faraway:assets
    • Butler suit les fichiers modifiés et ne met à jour que les parties nécessaires, ce qui évite d’avoir à gérer soi-même du hashing de fichiers ou un versioning spécial

1 commentaires

 
GN⁺ 2024-08-11
Avis de Hacker News
  • De superbes polices, et l’article est intéressant
    En voyant le faux jeu en haut à droite https://chevyray.dev/blog/creating-175-fonts/old_previews.pn..., je me suis dit que ce serait bien si c’était un vrai jeu
    J’aime bien son ambiance, un peu « Wonder Boy in Monster World pour GBA »
    Attention toutefois : à lire la licence, il ne semble pas permis d’utiliser les TTF dans un projet logiciel open source
    Je ne suis pas juriste, mais la dernière clause se lit clairement comme une interdiction : https://github.com/ChevyRay/pixel_font_megapack_license/blob...

    • Si vous aimez les jeux de plateforme, essayez Celeste
      La scène de cette maquette fait référence à la scène d’ouverture de Celeste
    • Il est clairement interdit de distribuer la police elle-même sous une forme open source ou CC, mais il est plus ambigu d’y voir une interdiction de l’inclure et de la distribuer avec un logiciel dont le reste est open source
      L’intention semble clairement être de l’utiliser dans des jeux au stade de produit final, où l’open source est relativement rare, plutôt que dans des moteurs de jeu ou des templates
      En lisant cet article, un autre cas limite du droit d’auteur m’est venu à l’esprit : aux États-Unis, une fonte (typeface) n’est pas protégée par le droit d’auteur
      Une police est protégée en tant que programme informatique, mais ce n’est pas le cas d’une fonte ni d’une simple police bitmap
      Ce workflow revient donc à partir d’une tilesheet source non protégée par le droit d’auteur pour créer un TTF protégé, puis à revenir à une tilesheet/un atlas de sortie qui n’est pas protégé non plus
    • Il aurait fallu écrire dans un projet logiciel open source, et non « dans un logiciel open source »
  • Vraiment impressionnant
    Créer un jeu de polices complet peut facilement prendre un an
    Il faut créer tous les glyphes de « A » à « Z », majuscules et minuscules, parenthèses, esperluette, point d’exclamation, etc., et si possible aussi des variantes comme le gras et l’italique
    Sans ces variantes, l’utilité de la police est limitée
    Ce qui fait particulièrement la différence, c’est le crénage, c’est-à-dire l’espacement entre les lettres, et on peut s’y perdre sans fin si l’on est obsessionnel
    Le corps de l’article explique aussi que, pour prendre en charge 176 caractères, il peut y avoir jusqu’à 176² = 37 976 paires de crénage à saisir ; l’auteur a donc créé ses propres outils pour en semi-automatiser la majeure partie, et ne saisir à la main que ce que l’algorithme ne couvrait pas

    • Cela vaut si l’on limite la police à un usage purement anglais
      Pour prendre en charge d’autres langues, même celles qui utilisent l’alphabet latin comme le français, l’espagnol, l’italien ou le portugais, il faut des caractères supplémentaires
      Ensuite, on peut avoir envie de prendre aussi en charge l’alphabet grec, le cyrillique, le japonais, le chinois, etc.
      Par exemple, selon Wikipedia, « les polices Noto prennent en charge plus de 77 000 caractères, soit environ la moitié des 149 186 caractères définis dans Unicode 15.0 »
    • Un jeu de polices complet peut facilement prendre un an, mais créer une famille de polices peut devenir le projet de toute une vie
    • Franchement, l’affirmation selon laquelle « un jeu de polices complet prend facilement un an » ne me convainc pas
      On peut s’acharner indéfiniment sur n’importe quoi
      Des domaines comme les langues, l’écriture, la musique ou la calligraphie semblent aussi attirer fortement les personnes à tendance obsessionnelle
      Le point, c’est que ce genre de remarque ressemble à une façon de dresser une barrière à l’entrée
      Les propos qui risquent de décourager quelqu’un de se lancer dans un domaine sont toujours un peu sensibles
  • Très bien
    Une chose m’intrigue : pourquoi avoir choisi ce sous-ensemble de caractères spéciaux scandinaves
    Le suédois utilise äöå, le norvégien et le danois utilisent æøå, mais cette police contient æ et pas ø
    Donc, même en retirant æ, la prise en charge du suédois resterait intacte, et en ajoutant ø, on pourrait aussi prendre en charge le norvégien et le danois
    Je me demande si c’est un simple oubli, ou s’il existe une locale qui utilise æ mais pas ø
    Pour référence, je ne confonds pas æ avec la ligature œ, un glyphe distinct utilisé en français

    • L’islandais utilise ö au lieu de ø, mais il lui faut aussi ð et ý, absents de cette police
      Cela dit, Æ apparaît aussi dans de vieux textes anglais comme « encyclopædia » ou dans les pluriels de mots venus du latin : https://en.wiktionary.org/wiki/Category:English_plurals_in_-...
    • C’était tout simplement un oubli
      En fait, ce n’est qu’assez tard dans le projet que je me suis rendu compte que ø manquait dans mon jeu de caractères
      Il est certainement possible de l’ajouter à toutes les polices et de publier un correctif, mais j’attendais de voir s’il y avait assez de demande pour justifier ce travail
      Cela dit, pouvoir prendre en charge deux langues de plus serait plutôt chouette
  • J’ai aussi aimé certaines polices utilisées sur le site, ainsi que le style simple
    Heureusement, c’est expliqué dans un article séparé : https://chevyray.dev/blog/how-this-site-is-made/#catppuccin-...

  • Intéressant
    Je ne savais pas auparavant que, lorsqu’on encode une police pixel en TTF, elle est convertie en vecteurs
    Pour quelqu’un qui la charge dans un véritable moteur de rendu de texte, cela devrait même permettre un zoom/dézoom assez fluide
    Bien sûr, les moteurs de jeu qui utilisent les polices pixel quasiment en 1:1 peuvent faire exception

    • Cela permet de les utiliser aussi dans des éditeurs graphiques traditionnels comme Photoshop, InDesign, Affinity ou Aseprite
      Ces outils n’ont pas de notion de police pixel ; avec un TTF dont le hinting et l’anticrénelage sont désactivés, on peut donc les exploiter dans ces applications
  • Super
    C’est aussi chouette que ce travail ait aidé financièrement la personne qui l’a réalisé
    Le nom Chevy Ray me dit quelque chose du côté des jeux indé, mais je ne me souviens pas exactement de ce qu’il a créé
    Ça devait être vers 2010-2012, quelque chose dans la mouvance de VVVVVV, Nidhogg ou Canabalt

    • C’était Flashpunk
      Beacon était excellent aussi — ça me rappelle des souvenirs, et les jeux indé me manquent
    • Le jeu dont tu parles est probablement Beacon
    • Ikenfell
    • J’ai aussi vraiment beaucoup aimé Ikenfell
    • Flashpunk ?
  • Excellent
    Quand je vois des profils à la Léonard de Vinci comme l’auteur de cet article, ça me rappelle une époque où artistes et ingénieurs n’étaient pas clairement séparés, mais ne faisaient qu’un

    • Dans ce cas, je conseille de vraiment lire sur Léonard de Vinci
      Pas des articles du genre « top 10 des inventions de Léonard de Vinci »
      En réalité, il y avait une séparation assez nette entre les deux
      Moi aussi, je peux modéliser dans Maya un vaisseau spatial capable d’aller jusqu’à Alpha Centauri avec une dynamique douteuse et non vérifiée
      Mais on est loin de le construire réellement et de l’envoyer dans l’espace interstellaire
      Les dessins sont jolis et pleins d’imagination, certes
  • Avec Rust, il est étonnamment facile de faire en sorte que ce genre de travail s’exécute sur plusieurs cœurs
    Il peut suffire d’ajouter un seul appel dans une chaîne de fonctions

    • Rust est conçu dès le départ pour offrir la sûreté mémoire et la sûreté vis-à-vis des threads
      À condition de respecter les règles définies par le langage, le multithreading devient presque « gratuit »
      La loi d’Amdahl s’applique toujours, mais au moins l’appli ne vous explose pas au visage
    • Ce n’est pas propre à Rust
      Scala et Java prennent aussi ce genre de fonctionnalité en charge par défaut
  • C’est vraiment un excellent travail, et l’article est bon aussi
    Avec quelques astuces, beaucoup d’algorithmes pourraient sans doute être rendus plus rapides
    D’après ce que j’ai lu, une piste serait de remplacer les hash maps par des bitmaps et des tableaux d’index d’octets pour le rendu des caractères et le mapping des variantes ASCII
    Bien sûr, comme c’est déjà suffisamment rapide, ce n’est pas très important pour ce code

    • Content que tu en parles, c’est tout à fait juste
      Le site ne contient pas tout le code, mais en réalité il alloue et clone pas mal de chaînes et de structures de données
      Là où c’était évident, j’ai écrit du code optimal, et certaines parties comme la copie de bitmaps ou les tâches facilement parallélisables étaient si rapides qu’elles se terminaient instantanément, donc je n’ai même pas essayé d’optimiser le reste
      Mais ce serait possible
      On oublie facilement à quel point des langages proches du bas niveau comme Rust, C++ ou Go sont rapides, surtout quand on y ajoute les outils de base du multithreading et des files de tâches
  • Les personnes intéressées par les polices peuvent aussi jeter un œil à https://tomorrow.type.today/
    C’est un studio typographique qui crée d’excellentes polices originales et expérimentales
    Comme l’un des membres de notre équipe est passionné de typographie, nous constituons une collection de leurs travaux sur https://play.soot.com/tomorrowtypetoday

    • À noter que cette société est enregistrée en Russie