Aller au contenu principal Aller au pied de page

Création d'un module Composer : font-finder

«  Trouve toutes les polices de caractères installées sur un système (et davantage)  »

Retour

Un peu de contexte

Nous réalisons différents projets de développement autour de la spécification XSL-FO, que nous publions en sources ouvertes (OpenSource). Pour le dire en deux mots, XSL-FO permet notamment de générer des documents PDF.

Dans le cadre de ces développements, il nous arrive d'avoir besoin de certains utilitaires, qui, la plupart du temps, sont disponibles sous la forme de packages directement en ligne. Quand un package nous plait, il suffit de l'intégrer à notre projet avec une ligne de code, et le tour est joué.

Dans ce cas précis, nous cherchions à valider les polices de caractères détectées par l'option auto-detect d'Apache FOP[1]. Apache FOP se base sur le nom de la police, le fichier qui la contient, la graisse de la police, et si elle est en gras ou en italique (ou aucun des deux). Cela nous aurait permis de comparer le fonctionnement de cette option à d'autres implémentations de XSL-FO.

Un exemple de configuration d'Apache FOP avec uniquement la partie qui nous intéresse dans le cas précis. Les textes en français sont des commentaires pour faciliter la compréhension :

Configuration de logiciel Apache FOP
<renderers> <renderer mime="application/pdf"> <fonts> <!-- Enregistre toutes les polices du dossier "C:\MyFonts1" --> <directory>C:\MyFonts1</directory> <!-- Enregistre toutes les polices du dossier "C:\MyFonts2" et ses sous-dossiers --> <directory recursive="true">C:\MyFonts2</directory> <!-- Détecte automatiquement les polices installées dans le système d'exploitation --> <auto-detect/> <!-- On peut aussi préciser des polices comme ceci, avec le nom de fichier, leur nom, leur style... --> <font metrics-url="arial.xml" kerning="yes" embed-url="arial.ttf"> <font-triplet name="Arial" style="normal" weight="normal"/> <font-triplet name="ArialMT" style="normal" weight="normal"/> </font> </fonts> </renderer> </renderers>
<renderers> <renderer mime="application/pdf"> <fonts> <!-- Enregistre toutes les polices du dossier "C:\MyFonts1" --> <directory>C:\MyFonts1</directory> <!-- Enregistre toutes les polices du dossier "C:\MyFonts2" et ses sous-dossiers --> <directory recursive="true">C:\MyFonts2</directory> <!-- Détecte automatiquement les polices installées dans le système d'exploitation --> <auto-detect/> <!-- On peut aussi préciser des polices comme ceci, avec le nom de fichier, leur nom, leur style... --> <font metrics-url="arial.xml" kerning="yes" embed-url="arial.ttf"> <font-triplet name="Arial" style="normal" weight="normal"/> <font-triplet name="ArialMT" style="normal" weight="normal"/> </font> </fonts> </renderer> </renderers>

Note : Ce code provient de ces deux pages de documentation :

Pour valider ces options, nous recherchions donc un package permettant de récupérer automatiquement les polices de caractères fournies avec le système d'exploitation (l'équivalent de l'option <auto-detect>), et éventuellement d'y adjoindre une liste de dossiers arbitraires (l'équipe de l'option <directory>). Et on n'a rien trouvé de vraiment pertinent.

Par "vraiment pertinent", il faut comprendre notre procédure pour intégrer du code externe. On vérifie toujours si un package est réellement pertinents dans notre contexte, notamment :

  • La performance
  • Les mises à jour fréquentes si le projet le nécessite
  • Le nombre de téléchargements élevé. S'il est faible, on regarde le code source de la bibliothèque

Ces vérifications sont nécessaires, parce qu'il est toujours difficile de supprimer une dépendance une fois devenue une brique fondamentale d'un projet. En étant précautionneux, on gagne du temps pour l'avenir et on réduit la dette technique.

En tout état de cause, le seul package trouvé était Phenx PHP Font Lib mais deux problèmes de taille ont surgi :

  • Un problème de performance : ce package est très lent pour notre usage, parce qu'il récupère de nombreuses informations dont nous n'avons pas besoin
  • Un problème de fonctionnalité : ce package ne gère qu'une petite partie des polices existantes ; TTF (TrueTypeFont), OTF (OpenTypeFont), WOFF (WebOpenFontFormat). Nous avons besoin à minima des polices WOFF2 et TrueTypeCollection en plus de celles-ci.

Après cette recherche, nous nous sommes dit que nous pourrions créer notre propre code et le rendre disponible sous la forme d'un package : ça ne devrait pas être bien long pour notre cas !

Haha.

Première étape : se baser sur le code d'Apache FOP

Quand on souhaite porter une fonctionnalité d'un outil existant dans un autre langage, transposer le code est souvent la meilleure option. Dans le cas d'Apache FOP, c'est un outil qui existe depuis 1999, avec une communauté qui effectue toujours des mises à jour. L'outil est stable et fonctionnel, c'est pile ce qu'il nous faut.

Le code d'Apache FOP est disponible pour Windows[2]. Et globalement, nous avons repris la partie du code qui nous intéressait à l'identique.

De même pour le code associé aux systèmes d'exploitations macOS (Darwin) et Linux. Cependant, nous n'avons pas trouvé dans le code d'Apache FOP les environnements BSD et Solaris, renvoyées par la constante PHP_OS_FAMILY. Ce n'était pas grand chose, donc après un peu de recherches, nous avons inclus ces environnements à la bibliothèque.

Deuxième étape : ajouter WOFF2

Le format WOFF2 est très intéressant dans le monde informatique moderne, pour son poids très faible. Chaque fichier ne peut contenir qu'une seule police de type TrueType ou OpenType. Sur Wikipedia, on peut voir ce paragraphe[3] en anglais :

WOFF 2.0 significantly improved compression efficiency compared to WOFF 1.0, primarily through the introduction of Brotli, a new byte-level compression algorithm developed by Jyrki Alakuijala and Zoltan Szabadka. Brotli's effectiveness led to its widespread adoption, notably for HTTP content encoding. WOFF 2.0 was standardized as a W3C Recommendation in March 2018, with Google providing the reference implementation.

Pour obtenir la police dans un fichier WOFF2, il nous faut donc décompresser le fichier, puis passer le résultat à un détecteur TrueType ou OpenType. Après un peu de recherches, il nous faut l'outil woff2_decompress qui n'existe en accès libre que pour un environnement macOS ou Linux. C'est embêtant après avoir mis en place un système fonctionnant sur Windows, BSD et Solaris. Les sources sont disponibles, il ne reste qu'à les compiler pour chacun des environnements.

Vient donc la création du fichier woff2.yml : ce qu'on appelle communément une *pipeline*, un fichier contenant toutes les actions à faire sur des serveurs fournis par GitHub. Les objectifs principaux de cette pipeline :

  • Pour chaque environnement, compiler woff2_decompress
  • Pour chaque environnement, vérifier woff2_decompress : c'est important de vérifier
  • Pour chaque environnement, copier woff2_decompress dans notre bibliothèque

Mais un environnement, ce n'est pas qu'un système d'exploitation, c'est aussi une architecture ! Pour ne donner que quelques exemples : Windows fonctionne en 32-bits, en 64-bits, en ARM, il existe les processeurs Mac Intel et les nouvelles puces M-quelque chose (M1, M2, ...). Bref, ce n'est pas une compilation, mais treize compilations !

Résultat, la pipeline se présente comme ceci : on vérifie d'abord si le code de Woff2 a changé, puis on construit pour tous les environnements (les Matrix), puis on vérifie, puis on envoie les exécutables dans l'outil développé.

Diagramme représentant le workflow en fonctionnement : pour les deux étapes (compilation et vérification), cinq blocs (un par système d'exploitation), avec chacun un à quatre tâches (les architectures matérielles).
Une dernière étape pour agréger les exécutables et les publier dans la bibliothèque"

Pour être honnêtes, il y a pas mal de choses à dire à ce sujet, mais restons concis :

  • Le code source de woff2_decompress fourni par Google est demandé de nombreuses fois pour Windows, mais à chaque fois la réponse vient de la communauté : Google semble avoir délaissé ce dépôt (comme le prouvent différentes issues restées sans réponses : Exemple 1, Exemple 2, Exemple 3).
    Nous aurions pu intégrer des exécutables trouvés ça et là dans notre bibliothèque, mais il était important pour nous de fournir les binaires de manière transparente, c'est à dire avec une pipeline ; télécharger un fichier exécutable sans savoir comment celui-ci a été construit nous semble délicat. Et cela n'aurait de toute façon été utile qu'avec Windows.
  • Les manières de compiler selon les environnements sont assez proches, mais différentes malgré tout. On a passé pas mal de temps à rechercher pourquoi sur tel environnement, la compilation ne fonctionnait pas. Il a fallu aussi naviguer au travers des conseils simplistes d'utiliser Act : si cela marche très bien pour Linux, ce n'est pas le cas pour MacOS (qui ne peut être émulé par Act), Solaris ou BSD (Act n'est visiblement pas prévu pour, car il utilise des commandes qui n'existent pas par défaut sur ces systèmes). Nous nous sommes posés la question de cacher ces tentatives de compilation sur l'historique Git, mais nous avons décidé de les laisser en toute transparence : si cela peut vous servir, n'hésitez pas à vous rendre dans l'historique d'exécution de la pipeline.
  • Nous avons essayé des modèles de langage (ChatGPT et Copilot) et les avons appliqués aux pipelines, par curiosité ou quand nous étions sans solution sur le moment. En résumé, pour une réponse valide à une question précise, environ cinq ajoutaient des options inutiles, ou changeaient le fonctionnement, ou inventaient des outils inexistants. Le gain de temps aura été évidemment négatif, mais des fois, il ne s'agit pas de produire mais de trouver de nouvelles pistes pour avancer.

A la fin de cette étape, nous pouvions décompresser les fichiers WOFF2, ce qui nous laisse avec... un fichier TTF ou OTF !

Troisième étape : ajouter TTF et OTF

Pour organiser un peu le développement, nous avons donc créé une structure de code standardisée appelée "décodeur", et chaque décodeur s'occupera d'un format. On aura donc un décodeur pour WOFF2, un pour TTF, un pour OTF, un pour TTC.

Chaque décodeur aura deux méthodes :

  • canExecute : est-ce que le décodeur peut s'exécuter sur ce fichier ? Ou, dit autrement, est-ce que le fichier correspond à ce décodeur ?
  • extractFontMeta : si canExecute est positif, alors récupérons les données du fichier.

Sans rentrer dans les détails, voici à quoi ressemble le décodeur WOFF2. Les commentaires (commençant par //) ont été ajoutés pour cette étude de cas :

Décodeur WOFF2
class WebOpenFontFormat2 implements FontDecoder { // La méthode canExecute regarde dans le contenu du fichier pour savoir // si celui-ci est bien un WOFF2 public static function canExecute(string $raw): bool { $signature = \substr($raw, 0, 4); // Si vous ne le saviez pas, tous les fichiers au format WOFF2 // commencent par... "wOF2". // Il est habituel que ce début de fichier, qu'on appelle fréquemment // "signature", fasse quatre caractères. return $signature === 'wOF2'; } // La méthode extractFontMeta extrait les données du fichier public static function extractFontMeta(string $raw, string $filename): array { // D'abord, on "dézippe" le fichier WOFF2. $ttf = self::decodeWoff2($raw); // Puis, on envoie le contenu "dézippé" au décodeur TrueTypeFont return TrueTypeFont::extractFontMeta($ttf, $filename); } // ...Il y a du code que nous avons retiré pour cette illustration... }
class WebOpenFontFormat2 implements FontDecoder { // La méthode canExecute regarde dans le contenu du fichier pour savoir // si celui-ci est bien un WOFF2 public static function canExecute(string $raw): bool { $signature = \substr($raw, 0, 4); // Si vous ne le saviez pas, tous les fichiers au format WOFF2 // commencent par... "wOF2". // Il est habituel que ce début de fichier, qu'on appelle fréquemment // "signature", fasse quatre caractères. return $signature === 'wOF2'; } // La méthode extractFontMeta extrait les données du fichier public static function extractFontMeta(string $raw, string $filename): array { // D'abord, on "dézippe" le fichier WOFF2. $ttf = self::decodeWoff2($raw); // Puis, on envoie le contenu "dézippé" au décodeur TrueTypeFont return TrueTypeFont::extractFontMeta($ttf, $filename); } // ...Il y a du code que nous avons retiré pour cette illustration... }

Tout ça c'est très bien, mais maintenant, il faut rédiger le décodeur pour les fichiers TTF !

Il est important de noter ici que nous n'avions qu'une connaissance très parcellaire des formats de police à ce moment du développement. Nous savions que les fichiers TrueType étaient des fichiers binaires, contenant des métadonnées (gras, italique, nom de la police), et qu'il existait d'autres formats pour stocker des polices, mais c'était à peu près tout.

Un fichier TTF (et plus généralement tous les fichiers binaires) sont un peu comme des mètres-rubans, où chaque centimètre contient une "case" avec une lettre. Et où on se met d'accord que telle information démarre à telle case, pour tant de cases.

Un mètre ruban

Pour imager, un exemple : si nous voulions créer un fichier binaire pour nos packages, on pourrait dire :

  • Le nom de la structure pour 20 cases
  • Le nom de la bibliothèque pour 20 cases
  • La date de rédaction de cette étude de cas au format JJ-MM-AAAA, avec 2 cases pour le jour, 2 cases pour le mois, 4 cases pour l'année.

Cela pourrait donner (les points sont là pour représenter des cases vides) :

Bloc de code
LS-A................FONT-FINDER.........18032026
LS-A................FONT-FINDER.........18032026

Pour trouver les informations que nous souhaitons dans un fichier TTF, il faut savoir à quelle case chercher. En deux mots, les fichiers TTF sont divisés en tables, ayant chacune un nom de quatre caractères (head, OS/2, post, ...) et contenant chacune des informations différentes.

Le plan a donc été :

  • Savoir dans quelles tables sont les informations qui nous intéressent, en se documentant
  • Créer un code pour :
    • Détecter l'ensemble des tables pour savoir où elles à quel endroit du "mètre-ruban" elles se trouvent
    • Se rendre dans la table concernée, et lire la bonne case

Et cela fonctionne très bien, après quelques bugs anticipés de type "je ne lis pas la bonne case". C'est incroyable comment se tromper d'une seule case décale tout !

Si vous suivez, vous aurez remarqué que nous n'avons pas du tout parlé d'OpenType, seulement de TrueType. Pour les données qui nous intéressent, elles sont stockées exactement au même endroit. TrueType est un format inventé par Apple et sous licence, tandis qu'OpenType est un format à marque déposée créé par Microsoft pour concurrencer Apple.

Une pierre deux coups : TTF et OTF sont supportés, et par la même occasion WOFF2 !

Quatrième étape : ajouter TTC et OTC

Les formats TTC (TrueTypeCollection) et leur contrepartie OpenType sont des fichiers TrueType contenant plusieurs polices en un seul fichier. Nous en avions besoin, car de nombreuses polices fournies sur MacOS sont dans ce format.

Un fichier TTC contient plusieurs polices TTF, les unes à la suite des autres, et chacune contient sa structure de tables avec ses métadonnées. En théorie c'était réalisable, mais nous n'avions pas assez de connaissances pour faire cela sans recherches préalables. Pour avoir un prototype, nous avons recouru à l'intelligence artificielle et le code généré n'était absolument pas fonctionnel. Mais pour le corriger, retour à la case départ : il fallait davantage d'informations.

Pour changer notre fusil d'épaule, nous avons cherché d'autres inspirations. Et nous avons trouvé ce projet getfontname. Après installation et lancement, les données d'un fichier TTC nous sont apparues.
Il suffisait donc de comprendre le fonctionnement et de l'adapter si besoin. Merci à mu2019 pour cette publication, car même si nous avons créé notre propre implémentation sans réutiliser ton code, il nous a bien aidé dans notre compréhension !

L'éléphant au milieu de la pièce

Jusque là, tout se passait comme n'importe quel projet. Et à vrai dire, si l'outil avait été fini après TTC et OTC, nous n'aurions pas rédigé ce texte.

Le vrai problème, c'est qu'en demandant à détecter les polices de caractères du système d'exploitation actuel, il faut savoir quel formats de police sont disponibles sur Windows, macOS, Linux, BSD et Solaris. Et si ces formats sont différents de TrueType et de WOFF2, alors la détection automatique ne fonctionnerait pas. Notre outil aurait été extrêmement dysfonctionnel.

Donc, la question centrale est devenue : combien de formats trouve-t-on sur des systèmes d'exploitation potentiellement vieux, potentiellement obsolètes, potentiellement oubliés ? Et la réponse est évidente : "plein".

Il y a vraiment plein de formats. Pour donner juste quelques exemples :

Et pour rajouter de la difficulté : toutes ces polices ne sont pas en binaire ; par exemple, JHF et SVG utilisent des caractères standards, que l'on peut lire et écrire.

Pour chacun de ces formats, il fallait donc :

  • Trouver des exemples de fichiers en ligne, sans les générer nous même avec des convertisseurs. Il fallait des fichiers originaux, car ce sont eux que l'on retrouvera en utilisant notre package
  • Trouver des informations sur la structure interne du fichier, pour détecter les données souhaitées
  • Rédiger le décodeur pour ce format de fichier

Au moment de la sortie de cette bibliothèque, trente décodeurs étaient présents.

On ne vous le cache pas, pour trouver certaines spécifications, c'était une sacrée course d'orientation. Et si vous êtes béats de l'intelligence artificielle, on vous arrête tout de suite : l'IA ne fait qu'inventer pour des spécifications obscures et oubliées depuis des décennies. On le sait, on a essayé.

Au fur et à mesure de la rédaction de ces décodeurs, on est tombés sur plein de petits détails de l'histoire de la typographie. Le fait que dans un fichier TTF, il y ait une table OS/2 par exemple. C'est une table ajoutée par Apple pour respecter une compatibilité avec le format OpenType de Microsoft[4]. Et dans le format OpenType, Microsoft l'a ajouté pour respecter une correspondance avec IBM[5], co-créateur avec Microsoft du système d'exploitation OS/2 dans les années 1990[6]. Dans tous ces fichiers que l'on utilise au quotidien, il y a une référence à un système disparu.

Ou encore, une des raisons pour la populatiré des polices Type1 à la fin des années 1990. Ces polices, créées pour fonctionner avec les imprimantes et les outils Adobe, ont inclus ce qu'on appelle le font hinting[7], permettant de mieux placer les caractères sur une grille. Quelque chose qui était inutile dans un terminal, mais qui est devenu bien plus important avec l'inclusion de caractères non-alphanumériques et avec l'essor du numérique graphique. Pour cela, il a fallu intégrer une bonne dose de mathématiques, et PostScript a très bien rempli son rôle, en tant que langage de programmation que l'on peut directement intégrer dans les fichiers de polices.

Au final, de page Wikipedia en article technique, de spécification en réflexions sur quel format était disponible à quelle époque, cette bibliothèque est devenue bien plus qu'un outil technique : à nos yeux, c'est ériger un musée, modeste peut-être mais bien présent, en l'honneur des évolutions typographiques de l'informatique. On ne pense pas créer de sites comme https://vetusware.com/ ou https://int10h.org/ de sitôt, mais si nos découvertes peuvent perpétuer l'histoire de l'informatique aux côtés de toutes les personnes passionnées par le retrocomputing, on en sera ravis.

Nettoyage, tests et performance

Nous n'avons pas tous la même approche de l'organisation du développement au sein de l'entreprise, et cela dépend aussi des projets : parfois, nous avançons étape par étape et nettoyons le code à chacune de nos étapes ; des fois, nous avons besoin de voir plus loin qu'une étape, et réalisons une grande portion du code avant de retravailler notre production.

Pour ce projet, nous avons fait de nombreux tests sur chacun des décodeurs et avons avancé à vue, comme souvent quand il faut agréger plusieurs spécifications dans un seul outil.

A l'aboutissement fonctionnel de la bibliothèque, on y retrouvait donc toutes ces choses qui empêchent de faire évoluer un projet dans la durée :

  • Des copiers/collers
  • De nombreux endroits qui manquaient de documentation
  • Du code désactivé (commenté) parce que devenu inutile
  • Des blocs de code considérés comme fragiles et qui pouvaient causer des erreurs à l'avenir
  • Des scripts ad-hoc pour tester si tel ou tel décodeur fonctionne, sans structure précise
  • Et des optimisations possibles en termes de performance

S'arrêter à cet état, et publier la bibliothèque telle quelle, ce serait comme faire des travaux dans un immeuble et laisser tous les outils, gravats et poussières partout. Alors on a rangé.

Pour ranger du code PHP, nous utilisons deux outils d'analyse statique, que l'on appelle des linters, ainsi qu'un beautifier.

Tout d'abord, la référence du domaine, PHPStan. Il permet de détecter tous ces codes fragiles, mal définis, qui pourraient plus tard causer du tort. Le problème de PHPStan, c'est qu'il ne s'intéresse pas à la documentation, ou très peu.
Nous utilisons également PHPCS Fixer en parallèle, pour détecter tous les codes insuffisamment documentés.
Enfin, nous utilisons Pint comme beautifier, pour automatiquement corriger les erreurs d'alignement dans le code, supprimer ou ajouter des lignes pour améliorer la lisibilité, etc.

Les personnes ayant déjà travaillé avec un linter configuré pour être très strict savent le temps que cela prend de documenter, standardiser et adapter du code existant pour qu'il soit lisible, structuré et cohérent. Si vous ne connaissez pas du tout le domaine, sachez que pour cette bibliothèque une dizaine d'heures a été nécessaire.

Une fois le code bien documenté et bien organisé, il était temps de standardiser les tests que nous avions créé. Nous avons utilisé PHPUnit, la référence en PHP, pour créer une structure cohérente et pouvoir lancer tous les tests en un seul coup. Ces tests sont actuellement exécutés à chaque modification du code, automatiquement, pour éviter au maximum les régressions. Cela permet également de tester sur tous les systèmes d'exploitation.
Dans tous nos tests, nous ajoutons des méta-tests pour nous assurer que nous n'oublions pas un fichier ou une fonctionnalité. Dans ce projet, un test vérifie que tous les décodeurs possèdent bien un test, par exemple.

Une fois le code propre et testé, il restait encore une étape. La bibliothèque fonctionne, et même bien, mais elle peut fonctionner mieux. Rendus à ce moment du développement, 1630 polices étaient parcourues en environ 15 secondes. Cela nous semblait réalisable de descendre à 10 secondes, peut-être 8, et ce serait fou d'arriver à 5 secondes.
Nous sommes parvenus à descendre à 9 secondes, ce qui est déjà pas mal du tout !

Pour optimiser du code, nous avons tout d'abord isolé les décodeurs les plus lents : en divisant le nombre de fichiers de polices par décodeurs, nous avoions déjà une idée du temps moyen par décodeur. Les coupables principaux étaient TrueTypeFont, TrueTypeCollection et PostScript, pour trois raisons différentes. On vous explique :

  • TrueTypeFont : il ne servait à rien de construire toutes les tables et lire la quasi-totalité du fichier pour notre bibliothèque : dès qu'on a ce qu'on veut, on s'arrête là !
  • TrueTypeCollection : par méconnaissance des différences entre la fonction unpack en PHP et unpack en Python, nous avions utilisé une bibliothèque de transposition de l'un en l'autre. Malheureusement, elle était particulièrement lente. En revenant à une syntaxe pure PHP, ça a été tout de suite beaucoup plus rapide !
  • PostScript : une erreur de code assez simple mais redoutable. Comme PostScript mélange du texte et du binaire, nous avions fait un "détecteur de binaire" assez basique, mais qui effectuait le test caractère par caractère. Sur des fichiers de 500 kilooctets, on arrive vite à un délai inacceptable.

Ce ne sont pas les seules optimisations, mais ce sont les plus notables. Ceci dit, ce délai de 9 secondes était assez variable selon le taux d'occupation et les performances de nos ordinateurs : il nous fallait quelque chose de plus déterministe, et surtout avec une idée pour chaque système d'exploitation.

Nous avons donc créé deux tests :

  • Un simple test de performance avec PHPBench tout d'abord : il exécute un code maximaliste cent fois, séparés en cinq silos, et mesure la moyenne de temps et l'écart type.
  • Pour avoir une vision plus précise par fichier, un script réalisé pour l'occasion : il découpe le temps par décodeur, et fait la moyenne du temps passé.

Si cela vous intéresse, vous retrouverez toutes les performances sur la page GitHub du projet : https://github.com/ls-a-fr/font-finder-php/.

On est un peu déçus de ne pas être descendus sous la barre symbolique d'une microseconde pour certains formats de fichier, mais qui sait, on arrivera peut-être à descendre plus bas dans une nouvelle itération !

L'avenir

Nous sommes conscients qu'il nous manque des formats. Si vous souhaitez nous aider à agrandir le musée et que vous possédez de vieux ordinateurs encore fonctionnels dans un coin de votre grenier, regardez leurs dossiers de polices. Vous trouverez peut-être :

  • L'evanescent format SNF sur Linux : un format qui devait apparemment être recompilé sur chaque machine et donc difficile à porter d'un ordinateur à un autre. Pendant la rédaction de cet article, on vient d'en trouver deux grâce à https://vetusware.com, ce qui explique que le décodeur n'existe pas encore. Dans tous les cas, ce n'est pas assez !
  • Les polices FNT, disponibles apparemment de Windows 1.0 jusqu'à peut-être NT 4.0.
  • Les polices F3, disponibles avec l'extension .f3a et .f3b : vraisemblablement sur les premières versions de SunOS, voire d'OpenSolaris
  • Les fichiers DFONT, SUIT, FFIL, MMM et AMFM sur les versions antérieures à OS X (Macintosh). Rassurez-vous, on ne les publiera pas sur le dépôt pour des raisons de licence. Par contre on en déduira des décodeurs.
  • Davantage de polices FON (Windows), disponibles de Windows 3.1 jusqu'à peut-être Windows XP. Idem, on ne les publiera pas, mais on renforcera notre décodeur.

Et nous verrons, peut-être dans les prochaines versions, pour prendre en charge les fichiers suivants que nous avons trouvés au cours de nos découvertes sur Wikipedia. Si vous en avez, on les accueillera avec plaisir !

BMF :
ByteMap Font Format
BRFNT :
Binary Revolution Font Format
MGF :
MicroGrafx Font
TDF :
TheDraw Font
UFO :
Unified Font Object

Si vous pensez qu'il nous manque un autre format que ceux listés ci-dessus, ou que vous souhaitez contribuer avec des fichiers ou des informations, n'hésitez pas à nous contacter par une issue sur ce dépôt.
Pas besoin d'avoir de connaissances techniques, on vous répondra !

Bibliographie

Référence et remerciements

Vous retrouverez la totalité des fichiers que nous avons intégré comme références et tests, ainsi que les sources et les personnes ou organisations que nous remercions chaleureusement ici : https://github.com/ls-a-fr/font-finder-php/blob/main/tests/samples/README.md.