Creare il proprio font partendo dalla propria grafia: reMarkable e librerie open source

Immagine di copertina

Uno dei progetti “weekend” più soddisfacenti che si possano fare con un tablet e-ink è trasformare la propria grafia in un font vero e proprio, installabile e utilizzabile in qualunque editor di testo, sito o documento. L’idea nasce da un articolo che mi ha incuriosita parecchio - I turned a photo of my handwriting into a real font, then open-sourced the whole pipeline - e da lì è nata la voglia di replicare (e adattare) l’esperimento usando un reMarkable come strumento di acquisizione al posto della classica foto scannerizzata.

In questo articolo vediamo la pipeline completa, passo per passo, con gli strumenti open source necessari.


Cosa vedrai

L’idea di partenza

L’articolo di riferimento parte da una foto di un foglio scritto a mano, che trasforma in un file binario, isolando le lettere e convertendolo in curve vettoriali per poi assemblarle in un font con FontForge, noto strumento open source per la creazione e modifica di font.

La pipeline è semplice concettualmente, ma nella pratica nasconde diversi dettagli: allineamento della baseline, rumore della scansione, coerenza dello spessore del tratto, kerning (tradotto: spaziatura tra i caratteri).

Per questo ho voluto provare a usare il mio reMarkable al posto di una foto: invece di scrivere su carta e poi scansionare, si scrive direttamente sul tablet con la penna e si esporta il risultato come SVG o PNG vettoriale ad alta risoluzione, saltando completamente il problema della binarizzazione da foto (ombre, prospettiva, illuminazione non uniforme).

Perché il reMarkable è un buon punto di partenza

Il reMarkable ha alcune caratteristiche che lo rendono comodo per questo scopo:

  • il tratto è già digitale: ogni pennellata è una sequenza di punti con pressione e velocità, non un raster rumoroso da ripulire;
  • esportazione nativa: l’app reMarkable (desktop o cloud) permette di esportare le pagine come vettoriale, con curve già pulite;
  • superficie e-ink ad alta precisione: il digitalizzatore Wacom (sia su reMarkable 2 che su Paper Pro) cattura tratti con una fedeltà che una foto di un foglio scritto a penna difficilmente eguaglia;
  • griglia guida: si può disegnare (o importare come template) una griglia di caselle, una per ogni glifo, così da avere già baseline e allineamento corretti al momento della scrittura.

Questo non significa che il PNG/foto non funzioni, anzi, è l’approccio originale dell’articolo, ed è assolutamente valido, ma partire da un SVG vettoriale elimina uno degli step più delicati della pipeline: la vettorizzazione da bitmap rumorosa.

La pipeline in breve

Lo schema complessivo è questo:

  1. si crea (o si scarica) un template con una cella per ogni carattere da disegnare (A-Z, a-z, 0-9, punteggiatura di base);
  2. si importa il template sul reMarkable e si scrive un glifo per cella, con la penna;
  3. si esporta la pagina come SVG;
  4. uno script Python isola ogni cella, ne estrae il contorno vettoriale del glifo;
  5. FontForge (tramite il suo binding Python) importa ogni contorno come glifo di un font, assegnandolo al codice Unicode corretto;
  6. si generano metriche, spaziatura e kerning di base;
  7. si esporta il font in formato TTF/OTF, pronto per essere installato.

Vediamo ogni step con gli strumenti open source coinvolti.

Step 1 - preparare il template dei glifi

Serve una griglia con una cella per carattere. La cosa più semplice è generarla con uno script che produce un PDF/SVG di pagine A4 (o della dimensione dello schermo reMarkable), ognuna con una griglia di quadrati numerati, ad esempio con reportlab o svgwrite:

import svgwrite

CHARS = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,!?")
CELL = 120  # px

dwg = svgwrite.Drawing("template.svg", size=("1404px", "1872px"))
for i, ch in enumerate(CHARS):
    x = (i % 10) * CELL + 40
    y = (i // 10) * CELL + 40
    dwg.add(dwg.rect((x, y), (CELL - 10, CELL - 10), fill="none", stroke="lightgray"))
    dwg.add(dwg.text(ch, insert=(x + 4, y + 20), font_size=12, fill="lightgray"))
dwg.save()

Il template va poi convertito in PDF (con cairosvg o rsvg-convert) e caricato sul reMarkable come nuovo documento.

Nota: nelle versioni più recenti dei remarkable, esistono già i notebook con dei template preformati: valuta se uno di questi può andare bene per il tuo scopo, altrimenti il template personalizzato è la strada più flessibile.

Step 2 - esportare i tratti dal reMarkable

Una volta scritto un glifo in ogni cella con la penna, si esporta il documento come SVG. Ci sono due strade:

  • usare l’app ufficiale (desktop o mobile), che offre l’export diretto in SVG/PDF vettoriale;
  • oppure, per chi preferisce restare da riga di comando, usare rmc o rM2svg, entrambi progetti open source che convertono i file .rm (il formato proprietario dei tratti reMarkable) in SVG.

Con rmc, ad esempio:

pip install rmc
rmc -t svg pagina.rm -o pagina.svg

Il risultato è un SVG con un path per ogni tratto di penna, e quindi esattamente il punto di partenza vettoriale di cui abbiamo bisogno, senza passare da un raster.

Step 3 - da immagine a contorno vettoriale

A questo punto l’SVG esportato contiene i tratti grezzi, cella per cella. Serve isolare ogni cella e ripulire il contorno prima di darlo in pasto a FontForge. Le librerie principali:

  • svgelements o svgpathtools per manipolare i path SVG in Python;
  • Potrace (via il binding pypotrace), nel caso si preferisca comunque partire da un’immagine raster (ad esempio se si è esportato in PNG invece che SVG) e si debba vettorizzare;
  • Pillow per il crop delle celle e per eventuali operazioni di pulizia (rimozione rumore, thresholding) se si lavora con bitmap.

Uno script tipico ritaglia ogni cella in base alle coordinate della griglia, isola il path corrispondente al tratto scritto e lo normalizza (centra, scala all’altezza x, riporta all’origine):

from svgpathtools import svg2paths2

paths, attributes, svg_attr = svg2paths2("pagina.svg")
# per ogni cella, filtra i path che ricadono nel bounding box della cella
# e normalizza le coordinate rispetto alla baseline

Step 4 - costruire il font con FontForge

FontForge è l’editor di font open source per eccellenza, e offre un binding Python (fontforge module, o l’esecuzione di script tramite fontforge -script) che permette di automatizzare completamente la costruzione del font:

import fontforge

font = fontforge.font()
font.encoding = "UnicodeFull"
font.fontname = "MiaGrafia"
font.familyname = "Mia Grafia"
font.fullname = "Mia Grafia Regular"

for ch, svg_path in glifi.items():
    glyph = font.createChar(ord(ch))
    glyph.importOutlines(svg_path)  # SVG del singolo glifo, generato allo step 3
    glyph.width = 600  # larghezza di default, poi rifinita

font.generate("MiaGrafia.ttf")

Ogni glifo viene importato come contorno vettoriale e associato al proprio code point Unicode. importOutlines accetta direttamente file SVG o EPS, quindi lo script dello step 3 può salvare un SVG per singolo glifo e passarlo qui.

Step 5 - rifinire il font

Il font generato al passo precedente funziona, ma è “grezzo”: ecco cosa conviene sistemare a mano (o con script aggiuntivi) in FontForge.

  • Larghezza dei glifi (glyph.width): va calcolata in base alla larghezza reale del tratto scritto, altrimenti lettere strette (come i o l) risultano troppo distanziate.
  • Baseline e altezza x: tutti i glifi vanno allineati alla stessa linea di base; un piccolo errore qui si nota subito nel testo composto.
  • Kerning: FontForge include strumenti di auto-kerning (font.autoKern), ma per un font calligrafico personale spesso conviene rifinire manualmente le coppie più problematiche (AV, To, We…).
  • Hinting: per una buona resa a schermi piccoli, si può generare l’hinting automatico con font.autoHint(). Si parla di hinting quando si aggiungono informazioni al font per migliorare la leggibilità a bassa risoluzione, ma non è strettamente necessario se il font è destinato a stampa o schermi ad alta densità.
  • Coerenza dello spessore: se alcuni tratti scritti col reMarkable risultano più sottili di altri (dovuto a variazioni di pressione), si può normalizzare lo spessore del contorno con un leggero inset/outset uniforme su tutti i glifi, usando le funzioni di trasformazione di FontForge o della libreria fontTools.

Risultato finale

Una volta rifiniti tutti i glifi, font.generate("MiaGrafia.ttf") produce un file TTF (o .otf se si preferisce il formato PostScript) installabile come qualsiasi altro font di sistema. Da lì in poi, la propria calligrafia diventa un font utilizzabile in un editor di testo, in un documento, o persino su un sito web (via @font-face).

Limiti e cose da migliorare

Per quanto questo sia un esperimento divertente, ci sono sicuramente dei limiti da tenere a mente, per cui ecco alcune note oneste su cosa non funziona benissimo:

  • i legamenti (ad esempio ff, fi) non vengono generati automaticamente: se si vogliono legamenti calligrafici realistici, vanno disegnati come glifi extra e collegati tramite feature OpenType (GSUB);
  • la variazione naturale della grafia (lo stesso carattere scritto leggermente diverso ogni volta) si perde: un font ha un solo glifo per carattere, quindi il risultato è più “regolare” e meno organico della scrittura reale. Per un effetto più naturale, si possono generare varianti multiple dello stesso glifo e alternarle a runtime con feature OpenType calt (contextual alternates) - una tecnica comune nei font calligrafici commerciali;
  • la pressione della penna (che il reMarkable registra) va persa nella conversione a contorno vettoriale piatto: se si vuole un tratto con spessore variabile serve un lavoro più sofisticato di conversione stroke-to-outline che tenga conto della pressione punto per punto.

Risorse utili

  • Articolo originale - la pipeline da foto a font open source
  • FontForge - editor di font open source, con binding Python
  • rmc - conversione dei file .rm del reMarkable in SVG/altri formati
  • reHackable/maxio - strumenti community per il formato dati reMarkable
  • fontTools - libreria Python per manipolare font TTF/OTF a basso livello
  • svgpathtools - manipolazione programmatica di path SVG

Conosci meglio chi ha scritto questo articolo

Serena Sensini

Ciao! Mi chiamo Serena Sensini e sono la creatrice di @ TheRedCode.it. Ho aperto questo blog nel 2021 per raccontare il mio lavoro e il mondo dell’informatica a parole semplici, in piccole pillole e alla portata di tutte le persone.

Sono un’ingegnera informatica specializzata in ambito AI & NLP. Di giorno lavoro come CTO @ Welyk e come Innovation & Emerging Technologies Leader @ Dedalus, mentre di notte scrivo e sono autrice di 5 libri -per ora-. 🖊️

Foto di Serena Sensini

Partners

Community, aziende e persone che supportano attivamente il blog

Vuoi diventare partner?

Collaboriamo con community, aziende e strumenti del mondo tech che vogliono raggiungere la nostra community di dev ed engineer italiani. Scrivici per proporre una collaborazione.

✉️ Scrivici

Vuoi diventare tech content creator? 🖊️

Se ti va di raccontare la tua esperienza nel mondo tech, questo è il posto giusto.

Cerchiamo voci autentiche, esempi pratici e punti di vista utili per chi legge.

Scrivici a collaborazioni[at]theredcode.it con una proposta: idea, taglio del contenuto e una breve presentazione. Non vediamo l'ora di leggere la tua esperienza!

Invia la tua idea