Come Kimi K3 ha costruito un tratto di penna stilografica digitale
Volevamo portare in Lulucat Notes la penna stilografica direzionale di Freeform. La specifica era uno screenshot di scrittura a mano. Dopo due modelli, una domanda discriminante e un pennino ellittico, la penna ad acqua scrive come dovrebbe. Ricerca, codice e validazione sono stati realizzati da Kimi K3 su Fireworks.

Renderizzato dalla pipeline Metal di Lulucat Notes di cui parla questo articolo.
Lulucat Notes ha una penna normale e un evidenziatore. Lo strumento successivo sulla roadmap era una penna ad acqua — la penna stilografica direzionale che conosci da Apple Notes e Freeform, in cui i tratti verticali risultano spessi e quelli orizzontali sottili. La specifica di questo strumento non era un documento. Era uno screenshot: tre righe di scrittura a mano, con le parole “pencilkit”, “无边记” e “这种有方向的水笔能力” — questa capacità di penna ad acqua direzionale.
Come per la pipeline Metal precedente, il lavoro è stato svolto da Kimi K3, il modello open di Moonshot in esecuzione su Fireworks: misurazione, modellazione, codice e validazione. L’essere umano ha fornito lo screenshot, risposto a una domanda e valutato la sensazione su un iPad reale.
La specifica è uno screenshot
Un’immagine statica non può dirti perché un tratto è sottile. Può dirti solo quanto è sottile e dove. Il primo passo è stato quindi misurare. Abbiamo scansionato lo screenshot riga per riga e colonna per colonna, seguendo la deriva della linea mediana di ogni tratto per ricavarne la direzione, poi abbiamo convertito la larghezza della scansione nella larghezza reale usando il seno di quell’angolo:
| Tratto | Direzione | Larghezza reale |
|---|---|---|
| Asta ascendente della “l”, “pencilkit” | ≈ 78° | 27.3 px |
| Asta della “k”, “pencilkit” | ≈ 90° | 28 px |
| Tratto discendente verso sinistra di 力 | ≈ 66° | 25.7 px |
| Collegamenti del corsivo | ≈ 8° | 11 px |
| Orizzontali cinesi (横) | ≈ 0° | 6–11 px |
Il rapporto tra spesso e sottile è ≈ 2.5. Adattando
Versione uno: la larghezza dalla direzione
Il primo modello era quello ovvio. Calcolare una direzione per ogni punto in ingresso, trasformare la direzione in larghezza attraverso la curva adattata e incorporare il risultato nel raggio del punto al momento della cattura. La direzione veniva stimata causalmente — una media ponderata con decadimento esponenziale sugli ultimi punti dell’arco, calcolata nello spazio degli angoli raddoppiati in modo che un’inversione del movimento non annullasse la stima. Si usano soltanto i punti passati, quindi il tratto live e quello committato coincidono byte per byte.
Il builder ha superato il suo unit check: i percorsi sintetici orizzontale, verticale, a 45° e con inversione hanno tutti incorporato le larghezze teoriche — 0.99, 2.52, 2.00 e 0.99 punti. Per il rendering non serviva alcun codice nuovo: un tratto con raggio incorporato è solo una catena di timbri rotondi, e la nostra pipeline point-sprite li disegnava già.
Su iPad, all’essere umano sono bastati circa dieci secondi per respingerlo: “Questa è una penna artistica, non la penna ad acqua.”
Due spiegazioni per un’unica immagine
Perché dava una sensazione sbagliata? C’erano due spiegazioni candidate, e lo screenshot non permetteva di distinguerle:
- Blocco della direzione. La geometria del pennino obbliga gli orizzontali a restare sottili e i verticali spessi, qualunque cosa faccia la mano. È ciò che implementava la versione uno.
- Pressione e velocità. La penna è guidata dalla pressione, e il disegno del campione è solo la dinamica della scrittura a mano: i tratti discendenti vengono naturalmente premuti, i collegamenti sono naturalmente rapidi e leggeri.
Entrambe le spiegazioni producono uno screenshot con orizzontali sottili e verticali spessi. La differenza sta in ciò che succede quando premi forte su un tratto orizzontale. La versione uno lo mantiene sottile. Una penna sensibile alla pressione lo rende spesso. Abbiamo quindi posto all’essere umano una domanda: un tratto orizzontale premuto con forza deve diventare più spesso?
“No. Gli orizzontali restano sottili.”
Il blocco della direzione era confermato. Ma c’era ancora qualcosa che non andava, perché anche la versione uno bloccava la direzione.
La risposta era nelle estremità dei tratti
L’indizio successivo si trovava in cima alle aste ascendenti. Ingrandendo le aste della “l” e della “k” nel campione sono emerse due cose: un tratto rettilineo mantiene la stessa larghezza dall’inizio alla fine, e le estremità dei tratti sono tagli diagonali piatti — la forma di un pennino a scalpello che si solleva. Non punti rotondi. Non assottigliamenti dovuti alla pressione.

Era questo il vero significato della “sensazione di penna artistica”. La versione uno aveva modellato l’aspetto del campione — la larghezza come funzione della direzione stimata — ma non la penna. Un estimatore della direzione è un sensore: oscilla davanti a un input rumoroso, resta indietro nelle curve e arrotonda ogni estremità del tratto trasformandola in un cerchio. Un pennino reale non ha nessuno di questi problemi, perché non calcola nulla. La larghezza è geometria.
Versione due: un pennino ellittico
Il modello finale non ha alcun estimatore della direzione. Il pennino è un’ellisse orientata: asse maggiore orizzontale, asse minore fisso. I timbri di questa ellisse vengono disposti fittamente lungo il percorso del tratto, e tutto il resto deriva dalla geometria:
-
Un tratto orizzontale scorre lungo il bordo aperto, quindi ha sempre larghezza
— una linea sottile costante, qualunque sia la pressione. Esattamente la specifica confermata. -
Un tratto verticale attraversa l’intero asse maggiore:
, l’estremità spessa. -
Un tratto diagonale prende la larghezza della corda dell’ellisse perpendicolare alla direzione del movimento,
-
Le estremità dei tratti sono tagli ellittici — le estremità piatte a forma di pennino del campione, senza aggiungere altro.
-
La pressione scala solo l’asse maggiore,
, quindi aumenta il volume d’inchiostro sui tratti discendenti e non può mai ispessire un tratto orizzontale.
Dalle misure del campione abbiamo mantenuto
Il rendering richiedeva un solo nuovo fragment shader e nient’altro. Il formato dei vertici — posizione, diametro, colore — conteneva già tutto: il diametro è l’asse maggiore, mentre l’asse minore è una variabile uniform per pass. Lo shader valuta una SDF ellittica con la stessa rampa di copertura a mezzo pixel dei nostri timbri rotondi. È questo che la rende confrontabile pixel per pixel con l’implementazione di riferimento di Core Graphics (fillEllipse per timbro). La validazione ha superato il consueto gate: un corpus sintetico con due tratti di penna stilografica è stato renderizzato in entrambi i modi e confrontato pixel per pixel — zero differenze strutturali, e un tratto orizzontale controllato a campione misurava 12 px in entrambi i renderer.

Versione uno a sinistra, versione due a destra. Stesso input scritto a mano, stessa pipeline. Le estremità raccontano tutto.
Su iPad, la nuova penna ha superato subito la prova: “好,很好” — bene. Molto bene.
Conservare l’errore
La versione uno non è finita nel cestino. È un pennello interessante — semplicemente non è una penna ad acqua. Così è stata distribuita come prima voce di un nuovo menu di pennelli sperimentali, con il nome che le ha dato l’essere umano: 漏水的圆珠笔, la penna a sfera che perde. La barra degli strumenti ha ricevuto un pulsante a forma di fiaschetta che apre un elenco testuale degli esperimenti; aggiungere il successivo costa una riga in un registry. Un modello scartato non è lavoro sprecato se può essere distribuito come esperimento chiaramente etichettato.
Una sera di cicli
L’intero percorso — misurare, modellare, costruire, provare sul dispositivo, fare una domanda, rimodellare, ricostruire, validare — è durato una sera. Kimi K3 su Fireworks ha gestito l’intero lato tecnico del ciclo: progettare le scansioni di misurazione, proporre la domanda discriminante invece di indovinare una seconda volta, eliminare il proprio estimatore della direzione quando le prove hanno cambiato verso ed estendere l’harness di pixel-diff prima di toccare l’app. La velocità di inferenza di Fireworks ha mantenuto il ciclo interattivo — lunghi diff di Metal e Swift, script di analisi dei pixel e strumenti per il corpus arrivavano tutti abbastanza in fretta da lasciare come unico collo di bottiglia il giudizio umano.
Il modello di collaborazione era lo stesso del post sulla pipeline Metal, e ha funzionato anche qui: il modello è rapido e preciso; l’essere umano possiede il gusto e la verifica end-to-end. Una sola frase di feedback basato sulla sensazione — “penna artistica, non penna ad acqua” — è bastata perché il modello individuasse l’errore preciso di modellazione e lo sostituisse con un progetto più semplice.
Il modello giusto si è rivelato più piccolo di quello sbagliato. La versione due è stata distribuita con meno parti mobili della versione uno — nessun estimatore, nessuna finestra di smoothing, nessun esponente adattato. Il pennino non calcola la larghezza. Il pennino è la larghezza.