Le développeur qui a créé 175 polices pixel avec Rust
(chevyray.dev)- 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
butlerpour 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
- Avec 176 caractères pris en charge, le nombre de paires de kerning possibles peut monter jusqu’à
- 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*"
pifodé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
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
- La configuration inclut
- 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
tcomporte 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
RgbaImageet rassemblés dans unHashSetde structuresPoint - 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
- Les pixels blancs sont extraits de
- 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
Vaoultd’un pixel vers la gauche améliore le rendu
- Le kerning manuel est défini dans
manual_kerningdu TOML- Sous une forme comme
{ left = "V", right = "a", kern = -1 } - L’option
alts = trueest prise en charge pour éviter de déclarer séparément tous les caractères accentués - Elle mappe des caractères alternatifs comme
àáâãäåpoura, afin d’appliquer le même kerning
- Sous une forme comme
- 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 rapprocherVd’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_leftetskip_kerning_rightpermettent d’exclure certains glyphes dans une direction donnéerayonest 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()etend_table()
- L’outil d’export remplit les tables
- 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
- En rendant la police à la taille 16, chaque pixel devient exactement
- 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
serdepermet 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,advsont 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
- Toutes les lettres et quelques phrases de test
- Un extrait de la nouvelle They're Made out of Meat de Terry Bisson
- Des mots de test utilisant la stratégie de Text for Proofing Fonts: A farewell to The Quick Brown Fox
- Toutes les combinaisons de chiffres et les symboles monétaires
- Des paires de kerning en majuscules, minuscules et casse mixte
- Divers signes de ponctuation
- 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, commeFaraway - RegularetFaraway - 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
butlerfourni 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
- Le déploiement se fait sous une forme comme
1 commentaires
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...
La scène de cette maquette fait référence à la scène d’ouverture de Celeste
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
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
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 »
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
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_-...
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
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
Beacon était excellent aussi — ça me rappelle des souvenirs, et les jeux indé me manquent
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
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
À 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
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
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