API Lua de Fontista

Un script Lua travaille sur une copie de la fonte ouverte ; à la fin, tous ses changements s'appliquent d'un coup, en un seul pas d'annulation (Cmd ou Ctrl + Z le défait). Lua 5.4, avec la bibliothèque standard (math, string, table, utf8, os, io). Les scripts demandent une licence (édition du site) ou la version App Store ; la version d'essai les refuse.

Lancer un script

  • Fenêtre Scripts (menu Scripts › Fenêtre Scripts…) : coller le code, puis Exécuter (Cmd ou Ctrl + Entrée). La sortie de print s'affiche dessous.
  • Scripts › Exécuter un script Lua… : choisir un fichier .lua.
  • Dossier des scripts : chaque .lua qui s'y trouve devient une entrée du menu Scripts.
  • Greffon : un dossier dans le dossier des greffons, avec un fichier plugin.txt, devient un sous-menu.
  • Ligne de commande (édition du site avec licence) : fontista --lua script.lua fonte.fontista [sortie.fontista].
SystèmeDossier des scriptsDossier des greffons
macOS, édition du site~/Library/Application Support/Fontista/scripts~/Library/Application Support/Fontista/plugins
macOS, App Store~/Library/Containers/dev.thinkspark.fontista/Data/Library/Application Support/Fontista/scriptsmême dossier, plugins
Windows%APPDATA%\Fontista\scripts%APPDATA%\Fontista\plugins
Linux~/.local/share/Fontista/scripts~/.local/share/Fontista/plugins

Scripts › Ouvrir le dossier des greffons ouvre le bon dossier. Un plugin.txt ressemble à ceci :

name = Mes outils
script = arrondir.lua = Arrondir tous les coins
script = epreuve.lua = Exporter une épreuve

Chaque ligne script = fichier = libellé devient une entrée du sous-menu.

La fonte : font

font est une photographie de la fonte prise au lancement du script (en lecture seule).

ChampContenu
font.family, font.upmnom de famille, unités par cadratin (souvent 1000 : vérifiez-le)
font.masters[i]id, name, ascender, descender, x_height, cap_height, location ({wght = 400})
font.axes[i]tag, name, min, default, max
font.glyphsles noms des glyphes, dans l'ordre de la fonte
langlangue de l'interface, "fr" ou "en" (pour répondre dans la langue de l'utilisateur)

Les identifiants de master ressemblent à m01. Toutes les fonctions qui prennent un master attendent son identifiant, pas son nom.

Fonctions

FonctionEffet
glyph(nom){name, unicode, note, export, mark, layers}, ou nil
layer(nom, master){width, contours, empty, ink}, ou nil ; c'est une copie : la modifier, puis set_contours
set_contours(nom, master, contours)remplace le dessin du calque (le crée au besoin)
set_width(nom, master, chasse)chasse
add_glyph(nom [, code])ajoute un glyphe vide dans chaque master ; false s'il existe déjà
remove_glyph(nom), rename_glyph(ancien, nouveau)les composants suivent un renommage
set_unicode(nom, code ou nil)caractère du glyphe
set_note(nom, texte), set_mark(nom, 0..7 ou nil), set_export(nom, booléen)note, étiquette de couleur (0 rouge, 1 orange, 2 jaune, 3 vert, 4 cyan, 5 bleu, 6 violet, 7 gris), export
anchors(nom, master){top = {x = 250, y = 700}, _top = …}
set_anchor(nom, master, ancre, x, y)crée ou déplace une ancre (top, bottom, _top, entry, exit…)
components(nom, master){{base, dx, dy}, …} (lecture seule)
set_ink(nom, master, pinceau ou nil)fait du calque un calque de squelettes encré par ce pinceau, ou l'arrête
kern(master, gauche, droite, valeur)règle une paire (noms de glyphes ou de groupes)
kerning(master){gauche = {droite = valeur}}
batch("ligne")lance une commande en lot (plus bas) et rend son compte rendu
compile()la TTF compilée, en chaîne d'octets
export_ttf(chemin)compile et écrit une TTF ; rend sa taille
save(chemin)enregistre une copie .fontista
print(…)sortie dans la fenêtre Scripts, ou dans le terminal avec --lua

Les noms de glyphes sont les noms de production : A, a, zero…nine, period, comma, hyphen, eacute, acutecomb, f_i, a.alt1, uni202F… Une fonte neuve contient déjà le jeu Latin-1 (vide).

Format des contours

{ closed = true, nodes = {
    {x = 100, y = 0,   kind = "line"},
    {x = 100, y = 300, kind = "line"},
    {x = 155, y = 400, kind = "off"},          -- les points de contrôle précèdent le point qu'ils courbent
    {x = 245, y = 400, kind = "off"},
    {x = 300, y = 300, kind = "curve", smooth = true},
} }
  • Unités de la fonte, y vers le haut, ligne de base à 0, x depuis l'origine du glyphe.
  • Un contour fermé commence à son premier point sur la courbe et se referme sur lui ; des off placés en fin de liste courbent le segment de fermeture.
  • Deux off : courbe de Bézier cubique ; un : quadratique ; aucun : droite.
  • kind : "line" ou "curve" pour un point sur la courbe (le genre du segment qui y aboutit), "off" pour un point de contrôle, "move" pour le départ d'un contour ouvert. smooth = true garde les poignées alignées.
  • Sens : contours extérieurs dans le sens inverse des aiguilles d'une montre, contreformes dans le sens des aiguilles. batch("correct") corrige les sens, batch("overlap") fusionne les chevauchements.
  • Un contour ouvert (closed = false) ne se remplit pas : c'est un trait, à épaissir par batch("offset rx ry stroke round"), ou un squelette encré par un pinceau (set_ink).

Squelettes et pinceau

Un calque encré (set_ink) traite ses contours ouverts comme des squelettes : le pinceau les parcourt à l'écran, dans l'Aperçu et à l'export ; ses contours fermés restent des formes pleines. Un pinceau est une table {nib = "round" | "broad", width = 80, angle = 40, edge = 9} (aussi min, max, gamma, taper, smoothing, melt ; width règle min et max ensemble). Par nœud de squelette : w, la pression de 0 à 1, et cap, un bout coupé droit le long d'une ligne à cet angle en degrés (absent : bout rond). Par contour : ink donne à ce trait son propre pinceau.

set_contours("l", m, {{closed = false, nodes = {{x = 250, y = 760, kind = "line", cap = 0}, {x = 250, y = 0, kind = "line", cap = 0}}}})
set_ink("l", m, {nib = "round", width = 72})   -- fût monoligne de 72 unités, bouts coupés à plat sur les zones

Commandes en lot : batch("…")

batch agit sur une sélection de glyphes (par défaut tous) et un master (par défaut le premier). La sélection reste en place pour la suite du script : refaire batch("select all") après une opération ciblée.

CommandeEffet
select all / upper / lower / digits / name nom nom…glyphes visés par les commandes suivantes
master id-ou-nommaster visé
offset dx dy [expand|contract|stroke] [round] [keep]décaler le contour ; stroke fait de chaque contour une bande de demi-largeur dx (horizontale) et dy (verticale)
round rarrondir tous les coins au rayon r
fit pct, simplify tolréajuster les courbes ; réduire les nœuds
smooth, tidy, extremeslisser les nœuds ; mettre au net ; ajouter les extrêmes
overlap, correctfusionner les chevauchements ; corriger les sens
transform rotate deg / scale pct / slant degautour du centre de chaque glyphe
autospace [blanc] [profondeur]espacement automatique (blanc moyen par côté, profondeur des contreformes en %)
autokern [force] [replace] [all]crénage automatique des lettres de base
metrics-update, kern-clean [seuil]appliquer les clés de métrique ; retirer les paires inutiles
weight nom wght dx dy [exact], italic nom deg, width nom pctnouveau master plus gras, penché ou étroit
smallcaps, tabular, smallforms [sups] [subs] [frac]glyphes dérivés et leurs features
skeletonize [editable|faithful|exact], weightaxis light boldsquelettes au pinceau ; axe de graisse depuis le pinceau
anchors [hauteur], formsancres de liaison cursive (entry et exit), formes init et fina des écritures liées
autofeatures on|offfeatures générées à la compilation (kern, mark, liga, calt…)

Ligne de commande

fontista --lua script.lua fonte.fontista [sortie.fontista]

Le script voit la fonte ; s'il a changé quelque chose, le résultat est enregistré dans sortie.fontista (ou à la place de la fonte sans sortie). print écrit dans le terminal. Code de sortie 1 et message Lua en cas d'erreur. Programme sous macOS : /Applications/Fontista.app/Contents/MacOS/fontista ; sous Windows, fontista.exe ; sous Linux, fontista.

Conseils

  • Lire d'abord ce dont on a besoin (font.upm, les zones du master), ne jamais supposer 1000 unités.
  • layer() rend une copie : la modifier, puis set_contours ; la relire après une commande en lot.
  • Une erreur arrête le script et rien n'est appliqué : lire le message dans la sortie.
  • overlap est une union (règle non nulle) : un contour inversé ne creuse que là où il est dans l'encre.
  • Lua ne garde que la première valeur d'un appel qui n'est pas le dernier argument : f(g(), x) ne passe qu'une valeur de g. Faire rendre des tables plutôt que plusieurs valeurs.
  • Un script a accès aux fichiers de l'ordinateur comme tout programme : n'exécutez que des scripts dont vous connaissez la source. Ceux de la bibliothèque sont relus et testés par Thinkspark.