- Das im Dezember 2023 veröffentlichte 175 Pixel Font Megapack ist ein Pixel-Font-Projekt, bei dem eine eigene Rust-Toolchain die Font-Erzeugung, Qualitätstests und Auslieferung übernimmt
- Frühere Pakete enthielten 2016 12 und 2018 40 Fonts; das neue Paket startete mit dem Ziel, Qualität, Stil, Sprachunterstützung und Distributionsautomatisierung auf einmal deutlich zu verbessern
- Die neuen Fonts gehen über die frühere Beschränkung auf ASCII hinaus und unterstützen 176 erweiterte lateinische Zeichen für EFIGS; asiatische und nicht-lateinische Schriften wurden jedoch wegen Qualitäts- und Zeitaufwand ausgeschlossen
- Das Rust-Tool pifo erzeugt aus PNG-Tilesheets und TOML-Konfigurationen Glyphen-Konturen, automatisches Kerning, TTFs, Tilesheets und gepackte Texture-Atlanten und verarbeitet auch 175 Fonts in wenigen Sekunden
- Große Beispielbilder, automatisches Kerning und ein
butler-Deployment-Skript für itch.io reduzierten den Aufwand für manuelle Prüfung, Korrekturen und Uploads, sodass sich die Qualität von fast 200 Fonts schnell verbessern ließ
Von früheren Pixel-Font-Paketen bis zum Megapack
- Das erste Font-Paket von 2016 war ein Bundle aus 12 Fonts, das in der Zeit entstand, als die Arbeit an Ikenfell begann
- Die ursprünglich für das Spiel erstellten Fonts wurden verfeinert und um einige weitere ergänzt, um sie auf itch.io zu verkaufen
- Sie wurden in mehreren Indie-Spielen eingesetzt und kamen gut an
- Das zweite Paket von 2018 wuchs auf 40 Fonts an, auch die Qualität stieg deutlich
- Für besseres Satzbild in Texten wurden Kerning-Tabellen erstellt
- Außerdem wurden vorgefertigte Formate bereitgestellt, die sich in verschiedenen Game Engines leicht verwenden ließen
- Beworben wurde das Paket, indem die eigenen Fonts auf Screenshots von Spielen von Indie-Entwicklern gezeigt wurden
- Die früheren Pakete wurden in Hunderten Indie-Spielen eingesetzt, unter anderem auch in Nintendos Cadence of Hyrule
- Auch in Get in the Car, Loser von Love Conquers All Games wurden mehrere Fonts verwendet
- Nach dem Release von Ikenfell verbesserte der Entwickler trotz einer langen Burnout-Phase seine Rust-Kenntnisse und arbeitete weiter an Fonts, um irgendwann ein neues Pixel-Font-Paket zu erstellen
Ziele des Megapacks
- Das anfängliche Ziel für das neue Paket waren 100 Fonts, das Endergebnis wurden jedoch 175 Pixel-Fonts
- Die früheren Pakete enthielten jeweils 12 bzw. 40 Fonts
- Das neue Paket sollte Fonts für viele Genres bieten, etwa Sci-Fi, Fantasy, Horror, Farm- und Cozy Games
- Die größte Anfrage und Beschwerde zu den früheren Paketen war, dass sie nur ASCII-Zeichen unterstützten
- Das neue Paket nutzt einen erweiterten lateinischen Zeichensatz, um EFIGS zu unterstützen, also English, French, Italian, German und Spanish
- Der endgültige Zeichensatz umfasst 176 Zeichen
- Asiatische oder nicht-lateinische Sprachen wurden ausgeschlossen, weil die Zeichensätze dem Entwickler nicht vertraut genug waren, um die gewünschte Qualität zu erreichen, und die Produktion deutlich mehr Zeit gekostet hätte
- Da Game-UIs eine visuelle Hierarchie brauchen, sollte jeder Font nicht nur als einzelner Stil, sondern als Font-Familie entstehen
- Die Font-Familie Virtue enthält beispielsweise 20 Stile
- Entwickler können damit Größen und Gewichte variieren, ohne Fonts mit unterschiedlicher Anmutung mischen zu müssen
- Kerning war bei den früheren Paketen ein großer Zeitfresser
- Bei 176 unterstützten Zeichen kann die Zahl möglicher Kerning-Paare auf bis zu
176²steigen - Um nicht alle Paare manuell eingeben zu müssen, wurde der Großteil automatisch berechnet; nur die Stellen, an denen der Algorithmus nicht ausreichte, wurden manuell ergänzt
- Bei 176 unterstützten Zeichen kann die Zahl möglicher Kerning-Paare auf bis zu
- Auch Qualitätskontrolle und Auslieferung sollten automatisiert werden
- Zuvor musste man nach dem Beheben von Pixelfehlern oder Kerning-Bugs erneut exportieren, testen und direkt auf itch.io hochladen
- Die neue Toolchain sollte Beispieltexte und Kerning-Visualisierungen erzeugen, damit Probleme schnell gefunden und Korrekturen sofort überprüft werden konnten
Vorbereitung auf bessere Font-Design-Qualität
- Obwohl viel Erfahrung mit Pixel Art und Pixel-Fonts vorhanden war, hatte sich der Entwickler mit traditionellem Schriftdesign nie intensiv beschäftigt
- Während der Arbeit diente Richard Poulins Design School: Type als Referenz
- Das Buch wurde als Einstieg genutzt, um Begriffe und Konventionen des Schriftdesigns zu lernen
- Auch Fotos von Texten aus der Umgebung wurden als Referenzen gesammelt
- Kleine Ladenschilder, Museen, Galerien, Festivals, Plakate lokaler Veranstaltungen und Buchcover dienten als Material
- Ziel war nicht, Schriften zu kopieren, sondern Buchstabenformen, Unterlängen und Unterschiede zwischen schmalen und breiten Buchstaben zu untersuchen
- Beim Beobachten dekorativer Fonts im Freien fiel auf, dass viele „auffällige“ Fonts nicht jeden Buchstaben übermäßig verzieren, sondern die Dekoration auf Großbuchstaben konzentrieren und Kleinbuchstaben subtiler behandeln
Die Rolle des Rust-Tools pifo
- Um die Ziele zu erreichen, schrieb der Entwickler ein eigenes Rust-Programm namens
pifo - Das eigentliche Font-Design erfolgte in gewöhnlichen Pixel-Art-Tools
- Eingaben sind PNG-Tilesheets und TOML-Dateien für die Konfiguration
- Ein Beispielbefehl hat die Form
pifo --all --output "Faraway" --input "Faraway*"
pifoschneidet die Eingabebilder in einzelne Glyphen-Tiles, erzeugt Glyphen-Konturen, berechnet Kerning-Paare automatisch und exportiert TTF-Dateien- Zusätzlich werden weitere Formate erzeugt, die sich direkt in verschiedenen Engines verwenden lassen
- Die Arbeit an einzelnen Glyphen ist parallelisiert, sodass ein einzelner Font nahezu sofort verarbeitet wird
- Selbst wenn alle 175 Fonts nacheinander verarbeitet werden, dauert es nur wenige Sekunden
- Die wichtigsten verwendeten Rust-Crates waren:
Erzeugung der Glyphen-Konturen
- Jedes Font-Sheet besteht aus einem Tilesheet und einer TOML-Konfigurationsdatei
- Die Konfiguration enthält unter anderem
version,baseline,line_gap,spacing,metrics,auto_kerning,auto_kerning_min,manual_kerning,skip_kerning_leftundskip_kerning_right - Die Rastergröße kann variieren, muss aber immer ein einheitliches Raster sein, und die Zeichen müssen an festgelegten Positionen stehen
- Das Tool verarbeitet nur zu 100 % weiße Pixel; Schachbrett-Hintergrund und Grundlinie dienen lediglich als Hilfen
- Die Konfiguration enthält unter anderem
- TrueType-Glyphen bestehen aus einer oder mehreren Konturen (contours)
- Bei Pixel-Fonts muss für jede Gruppe verbundener Pixel, also jeden Cluster, eine Kontur erzeugt werden
- Wenn etwa beim Kleinbuchstaben
tzwei getrennte Pixelgruppen vorhanden sind, werden zwei Konturen benötigt
- Die Konturerzeugung erfolgt in mehreren Schritten
- Aus dem
RgbaImagewerden nur weiße Pixel ausgewählt und in einemHashSetausPoint-Strukturen gesammelt - Ausgehend von einem beliebigen Pixel wird per Flood Fill zu benachbarten Pixeln traversiert; das wird wiederholt, bis keine unbesuchten Pixel mehr vorhanden sind, um Cluster zu finden
- In jedem Cluster werden Seiten ohne angrenzende Pixel als freiliegende edge gesammelt
- Head und Tail der edges werden zu einem geschlossenen Pfad verbunden und in eine Kontur umgewandelt
- Aus dem
- Cluster mit Löchern können mehrere Konturen erzeugen
- Die äußere Kontur ist im Uhrzeigersinn gewunden, innere Löcher gegen den Uhrzeigersinn
- Dieser Richtungsunterschied entspricht der Art, wie TTF Löcher darstellt
- Zwischenpunkte auf durchgehenden Geraden werden entfernt
- Das ist eine Optimierung, um Dateigröße zu reduzieren und die Rasterisierung zu beschleunigen
Automatisierung der Kerning-Tabelle
- Nach den Konturen ist für die Erzeugung einer TTF eine Kerning-Tabelle erforderlich
- Kerning-Tabellen ziehen bestimmte Zeichenpaare nach links, damit Wörter natürlicher aussehen
- Beispielsweise sehen die Paare
Vaundltbesser aus, wenn sie um 1 Pixel nach links gezogen werden
- Manuelles Kerning wird in
manual_kerningin der TOML angegeben- Etwa in der Form
{ left = "V", right = "a", kern = -1 } - Um nicht alle akzentuierten Zeichen einzeln angeben zu müssen, wird die Option
alts = trueunterstützt - Dadurch werden Alternativzeichen wie
àáâãäåfüragemappt und erhalten dasselbe Kerning
- Etwa in der Form
- Automatisches Kerning wird berechnet, indem die rechte Glyphe jeweils um 1 Pixel nach links verschoben wird
- Gesucht wird die nächstliegende Position, an der sie die linke Glyphe nicht berührt
- Auch eine Berührung an den Ecken gilt als Kontakt
- Im Beispiel
LVkannVum 1 Pixel herangezogen werden, aber bei 2 Pixeln würden sich Pixel berühren; der Kerning-Wert ist daher-1
- Die automatische Kerning-Berechnung respektiert manuelle Werte und Ausschlusskonfigurationen
- Mit
skip_kerning_leftundskip_kerning_rightlassen sich Glyphen für eine bestimmte Richtung ausschließen - Mit
rayonwerden alle Kerning-Paare parallel berechnet
- Mit
Exportformate
- PIFO erzeugt nicht nur TTF, sondern auch Tilesheets und gepackte Texture-Atlanten
- TTF-Dateien sind Binärdateien aus mehreren Tabellen
- Das Export-Tool füllt die Tabellen
head,hhea,maxp,OS/2,hmtx,cmap,loca,glyf,kern,nameundpost - Für jede Tabelle müssen Position, Länge und Prüfsumme gespeichert werden; das erfolgt mit
begin_table()undend_table()
- Das Export-Tool füllt die Tabellen
- Die Grundgröße der Pixel-Fonts wird auf 16 gesetzt
- Beim Rendern in Größe 16 entspricht ein Pixel genau
1 px - Für eine Skalierung ohne Zittern sollte man in Vielfachen von 16 zeichnen, etwa
32,48oder64
- Beim Rendern in Größe 16 entspricht ein Pixel genau
- Der Tilesheet-Export ist anders als das Eingabe-Sheet nach Unicode-Codepoints sortiert
- Die zusätzlich erzeugte Datendatei enthält Zeilen und Spalten, Tile-Größe, Grundlinie, Zeilenabstand, Leerzeichenbreite, Glyphen-Metriken und Kerning-Tabelle
- Mit
serdewird in mehrere Formate wie JSON, XML und TOML serialisiert
- Auch ein gepackter Atlas wird erzeugt
- Dafür wird die eigene Rechteck-Packer-Crate crunch genutzt
- Da beim engen Packen Positionsinformationen verloren gehen, enthält der Atlas für das Rendering zusätzliche Daten wie
x,y,w,h,off_x,off_yundadv
Qualitätstests und Beispielbilder
- Um die gewünschte Qualität zu erreichen, wurde PIFO um eine Funktion zum Erzeugen riesiger Beispielbilder erweitert
- Die Beispielbilder bestehen aus mehreren Testblöcken
- Alle Buchstaben und einige Testsätze
- Ein Auszug aus Terry Bissons Kurzgeschichte They're Made out of Meat
- Testwörter nach der Strategie aus Text for Proofing Fonts: A farewell to The Quick Brown Fox
- Alle Zahlenkombinationen und Währungssymbole
- Kerning-Paare für Großbuchstaben, Kleinbuchstaben und gemischte Groß-/Kleinschreibung
- Verschiedene Satzzeichen
- Während der Arbeit konnten Beispielbilder sofort erzeugt werden, wodurch Probleme schnell gefunden und behoben werden konnten
- Dieser Prozess verbesserte die allgemeine Qualität und den Feinschliff von fast 200 Fonts
Automatisierung der itch.io-Auslieferung
- Das Endergebnis waren 175 Pixel-Fonts; als Online-Shop für Downloads wurde wie zuvor itch.io gewählt
- Der mühsamste Teil war, für jeden Font ein eigenes itch-Projekt anzulegen
- Diese Arbeit war pro Font nur einmal nötig
- Danach ließen sich Uploads und Wartung per Kommandozeilen-Skript erledigen
- Das Deployment-Skript besteht aus drei Schritten
- PIFO im Release-Modus kompilieren
- Die gewünschten Font-Assets bauen
- Das itch-Projekt jedes Fonts mit den neuen Assets aktualisieren
- Eingabemuster wie
--input "Faraway*"finden Stile mit demselben Präfix, etwaFaraway - RegularundFaraway - Bold, und bündeln sie zu einem Paket für eine Font-Familie - Für den finalen Upload wurde das von itch bereitgestellte Kommandozeilen-Deployment-Tool
butlerverwendet- Ausgeliefert wurde in der Form
butler push ../distro/faraway chevyray/pixel-font-faraway:assets - Da Butler geänderte Dateien nachverfolgt und nur die nötigen Teile aktualisiert, waren kein eigenes File-Hashing und keine spezielle Versionsverwaltung erforderlich
- Ausgeliefert wurde in der Form
1 Kommentare
Hacker-News-Kommentare
Tolle Fonts, und der Artikel ist auch interessant
Ich wünschte, das Fake-Spiel oben rechts https://chevyray.dev/blog/creating-175-fonts/old_previews.pn... wäre ein echtes Spiel
Es hat so eine Stimmung wie „Wonder Boy in Monster World für den GBA“, was mir gefällt
Man sollte aber auf die Lizenz achten; es scheint, als sei die Nutzung der TTFs in Open-Source-Softwareprojekten nicht erlaubt
Ich bin kein Anwalt, aber die letzte Klausel lese ich als eindeutiges Verbot: https://github.com/ChevyRay/pixel_font_megapack_license/blob...
Die Szene in diesem Mock-up orientiert sich an der Eröffnungsszene von Celeste
Die Absicht scheint eher zu sein, dass die Fonts in Spielen als Endprodukt eingesetzt werden sollen, wo Open Source relativ selten ist, und nicht in Game-Engines oder Templates
Beim Lesen musste ich auch an einen anderen urheberrechtlichen Grenzfall denken: In den USA sind Schriftbilder (typefaces) nicht urheberrechtlich geschützt
Fonts sind als Computerprogramme geschützt, Schriftbilder und einfache Bitmap-Fonts dagegen nicht
Damit läuft dieser Workflow im Grunde darauf hinaus, aus einer nicht urheberrechtlich geschützten ursprünglichen Tileset-Datei ein urheberrechtlich geschütztes TTF zu machen und dann wieder zu nicht urheberrechtlich geschützten ausgegebenen Tilesets/Atlanten zurückzukehren
Wirklich beeindruckend
Das Erstellen eines vollständigen Font-Sets kann leicht ein Jahr dauern
Man muss alle Glyphen von „A“ bis „Z“, Groß- und Kleinbuchstaben, Klammern, kaufmännisches Und, Ausrufezeichen und so weiter erstellen und wenn möglich auch Varianten wie fett oder kursiv
Ohne solche Varianten ist die Einsetzbarkeit eines Fonts eingeschränkt
Besonders entscheidend ist Kerning, also der Abstand zwischen Buchstaben, und wenn man sich darin verlieren will, kann man das endlos tun
Im Artikel steht auch, dass bei Unterstützung von 176 Zeichen maximal 176² = 37.976 Kerning-Paare eingetragen werden müssen; deshalb wurde ein eigenes Tool gebaut, um das meiste halbautomatisch zu erledigen und nur die Stellen manuell zu pflegen, in denen der Algorithmus nicht ausreichte
Wenn man andere Sprachen unterstützen will, braucht man selbst für lateinisch geschriebene Sprachen wie Französisch, Spanisch, Italienisch oder Portugiesisch zusätzliche Zeichen
Danach will man vielleicht auch noch griechische Schrift, Kyrillisch, Japanisch und Chinesisch unterstützen
Laut Wikipedia unterstützen „Noto fonts“ zum Beispiel mehr als 77.000 Zeichen, also etwa die Hälfte der 149.186 in Unicode 15.0 definierten Zeichen
In alles kann man sich endlos hineinsteigern
Es wirkt auch so, als würden Bereiche wie Sprache, Schreiben, Musik oder Kalligrafie Menschen mit Hang zur Obsession besonders stark anziehen
Der Punkt ist, dass so eine Aussage wie Gatekeeping klingt
Wenn Menschen entmutigt werden, die neu in ein Gebiet einsteigen wollen, wirkt das immer etwas heikel
Sehr schön
Ich frage mich nur, warum genau diese Teilmenge der skandinavischen Sonderzeichen gewählt wurde
Im Schwedischen gibt es äöå, im Norwegischen/Dänischen æøå, aber in diesem Font ist æ enthalten und ø fehlt
Damit bliebe die Unterstützung für Schwedisch auch ohne æ erhalten, und mit zusätzlichem ø könnte man auch Norwegisch und Dänisch unterstützen
Ich frage mich, ob das einfach ein Versehen war oder ob es eine Locale gibt, die æ nutzt, aber nicht ø
Zur Klarstellung: Ich verwechsle æ nicht mit der Ligatur œ, die im Französischen als eigenes Glyph vorkommt
Æ kommt allerdings auch in älteren englischen Texten oder in Pluralformen von Wörtern lateinischen Ursprungs vor, etwa in „encyclopædia“: https://en.wiktionary.org/wiki/Category:English_plurals_in_-...
Tatsächlich habe ich erst recht spät im Projekt gemerkt, dass ø in meinem Zeichensatz fehlte
Ich könnte das natürlich patchen und wieder in alle Fonts einbauen, aber ich wollte erst abwarten, ob dafür überhaupt genug Nachfrage besteht
Trotzdem wäre es ziemlich cool, damit zwei weitere Sprachen zu unterstützen
Mir gefielen auch einige der auf der Website verwendeten Fonts sowie das einfache Styling
Zum Glück gibt es dazu einen separaten Artikel: https://chevyray.dev/blog/how-this-site-is-made/#catppuccin-...
Interessant
Mir war vorher nicht klar, dass man Pixel-Fonts beim Kodieren als TTF in Vektoren umwandelt
Für Leute, die sie in einen ordentlichen Text-Renderer laden, ermöglicht das vermutlich auch einigermaßen sauberes Skalieren
Natürlich kann das für Game-Engines, die Pixel-Fonts fast nur 1:1 verwenden, eine Ausnahme sein
Diese Werkzeuge kennen das Konzept eines Pixel-Fonts nicht, daher kann man TTFs mit deaktiviertem Hinting und Antialiasing in diesen Apps nutzen
Großartig
Es ist auch schön, dass diese Arbeit der Person, die sie gemacht hat, finanziell geholfen hat.
Der Name Chevy Ray sagt mir aus der Indie-Game-Szene etwas, aber ich erinnere mich nicht genau, was er gemacht hat.
Irgendetwas aus dem Fahrwasser von VVVVVV, Nidhogg oder Canabalt, ungefähr um 2010–2012, glaube ich.
Beacon war auch großartig — das weckt Erinnerungen an früher, ich vermisse Indie-Games.
Hervorragend
Wenn ich solche Da-Vinci-Typen wie den Autor dieses Artikels sehe, muss ich an eine Zeit denken, in der Künstler und Ingenieure nicht klar getrennt waren, sondern eins.
Nicht solche Artikel wie „Die Top 10 Erfindungen von Da Vinci“.
In Wirklichkeit gab es zwischen beidem eine ziemlich große Trennung.
Ich kann in Maya auch ein Raumschiff modellieren, das mit ungeprüfter, dubioser Dynamik bis nach Alpha Centauri fliegt.
Aber das ist noch etwas ganz anderes, als es tatsächlich zu bauen und in den interstellaren Raum zu schicken.
Die Zeichnungen sind hübsch und fantasievoll.
In Rust ist es erstaunlich einfach, so etwas auf mehreren Kernen laufen zu lassen.
Es kann schon reichen, nur einen Aufruf in eine Funktionskette einzufügen.
Wenn man die von der Sprache vorgegebenen Regeln befolgt, ist Multithreading fast schon „gratis“.
Amdahls Gesetz gilt natürlich weiterhin, aber wenigstens explodiert die App einem nicht direkt vor den Augen.
Scala und Java unterstützen so etwas ebenfalls standardmäßig.
Wirklich großartige Arbeit, und der Artikel ist auch gut.
Mit ein paar Kniffen ließen sich viele der Algorithmen vermutlich noch schneller machen.
Nach dem, was ich gelesen habe, könnte der Schlüssel darin liegen, beim Zeichnen von Zeichen und beim ASCII-Varianten-Mapping die Hashmaps durch Bitmaps und byteindizierte Arrays zu ersetzen.
Für diesen Code ist das natürlich nicht besonders wichtig, weil er ohnehin schon schnell genug ist.
Auf der Website steht nicht der vollständige Code, aber tatsächlich werden ziemlich viele Strings und Datenstrukturen alloziert und kopiert.
An den offensichtlichen Stellen habe ich den Code optimiert, und Dinge wie Bitmap-Kopien oder Aufgaben, die sich leicht parallelisieren lassen, waren ohnehin so schnell erledigt, dass ich gar nicht versucht habe, andere Teile weiter zu optimieren.
Aber möglich wäre es auf jeden Fall.
Man vergisst leicht, wie schnell sprachnähere Low-Level-Sprachen wie Rust, C++ oder Go sind, erst recht, wenn man dazu noch die Standardwerkzeuge für Multithreading und Job-Queues nutzt.
Wer sich für Fonts interessiert, sollte sich auch https://tomorrow.type.today/ ansehen.
Das ist ein Typografie-Studio, das großartige originelle und experimentelle Fonts macht.
Jemand aus unserem Team ist tief in Typografie eingetaucht und baut eine Sammlung ihrer Arbeiten auf https://play.soot.com/tomorrowtypetoday auf.