Quill: a calligraphy model with no training
Quill writes text in six calligraphic hands: italic, foundational, blackletter, copperplate and brush for Latin letters, and shodo (Japanese brush calligraphy) for kanji and kana. Nothing in it was learned. The letters are pen paths from public data; the calligraphy comes from hand-set pens.
Try it:
- Web app: https://quill-calligraphy-b25f17930c4d.herokuapp.com/
- In your browser (Pyodide): Space: Vishwasaidev/quill
- Weights + model card: Vishwasaidev/quill
python server.py # web page on http://127.0.0.1:8792
python quill.py "Ars longa, vita brevis" --style italic --flourish
python quill.py "In the beginning was the word" --style blackletter --initial --seal VK
python quill.py "一期一会\n花鳥風月" --seal 和
python quill.py "永" --animate # animated .webp of the character being written, stroke by stroke
python quill.py --demo
python export_weights.py # Hershey + KanjiVG -> weights.safetensors
Styles: italic, foundational, blackletter, copperplate, brush, shodo (chosen automatically for kanji or
kana). Inks: iron, black, sepia, sumi, red, blue, green, gold, vermilion. --size is the cap height
in pixels (for shodo the character cell is 1.8 times that); --width is where lines wrap; shodo starts a new column
on each new line or after 6 characters. Requires only numpy and pillow.
Extras:
--initialdraws the first letter about twice the size in red, as in a rubricated manuscript.--sealcarves up to 4 characters (kanji or Latin) into a red seal stamp, white letters on red, with rough edges and patchy ink.--animatewrites an animated WebP of the page being written in stroke order.--flourishadds a tapered swash under Latin text.
How it works
| Layer | What it does | Numbers |
|---|---|---|
| Glyphs | each character is a list of strokes in writing order, each a list of points the pen passes through; kanji strokes also carry their kind (stop, dot, left sweep, right sweep, hook, rise) | glyphs.<font>.*, glyphs.kanji.* |
| 1 smooth | Chaikin corner cutting: every new point is a fixed 3/4 : 1/4 blend of two neighbours | smooth.chaikin (2x2) |
| 2 slant | shear and squeeze about each baseline | slant, squeeze per style |
| 3 pen | each step of the pen becomes one convex shape (see below) | nib angle, width, pressure rules |
| 4 raster | per pixel, one neuron per shape edge, d - nx*x - ny*y; min over a shape's edges (AND), max over shapes (OR); a one-pixel ramp gives antialiasing; dry-brush gaps are a fixed sine pattern across the stroke |
computed from the shapes |
| 5 ink | ink density times paper texture, composited over paper; the red initial and the seal are separate ink layers | ink colours |
The pens:
- broad (italic, foundational, blackletter): a flat nib held at a fixed angle and swept along the stroke. The stroke is thick where it moves across the nib and hairline where it moves along it, as with a real broad-edge pen. Each step is the convex hull of the nib at two neighbouring points, so this is exact, not approximate.
- pointed (copperplate): a round tip that swells only on strokes close to the slant axis, the way a flexible nib spreads under pressure on downstrokes.
- brush: a round tip whose size follows a fixed profile along each stroke: it presses in at the start and lifts off into a point at the end.
- shodo: a round brush whose pressure profile depends on the stroke's kind, as KanjiVG records it. Stops (tome) land with a press from the upper left, run steady, and press again to stop. Sweeps (harai) taper to a point, and the right sweep swells before it flicks off. Dots are teardrops, and hooks flick off at the end. Long strokes run dry towards their end, leaving bristle streaks.
weights.safetensors holds 2,506,381 numbers (9.8 MB): mostly the stroke points of 6,703 kanji and kana, plus the
Hershey letters, ink colours and Chaikin matrix, with the pen settings in its metadata.
Data and licences
- Hershey fonts: public domain (A. V. Hershey, US National Bureau of Standards, 1967), extracted from the
MIT-licensed
Hershey-Fontspackage. - KanjiVG: copyright Ulrich Apel, CC BY-SA 3.0,
http://kanjivg.tagaini.net. The kanji stroke data in
weights.safetensorsis derived from it, so that part of the file is under the same licence.
Limits
- The letterforms are borrowed. No training happened, but the letter shapes come from Hershey and KanjiVG. The pens, smoothing, slant, ink, seal and layout are hand-set.
- Hershey's letters are a technical font, not a calligrapher's hand. The italic is a slanted roman with an italic pen, not a true italic with branching arches. Blackletter uses Hershey's gothic letters, which are drawn as several parallel strokes; at large sizes thin gaps between them show, which looks engraved.
- Shodo is regular script (kaisho) only. KanjiVG gives textbook stroke paths, so there is no cursive (gyosho or sosho) running of strokes together, and every copy of a character is identical.
- Characters missing from the data are left out. Latin covers ASCII; kanji covers KanjiVG's 6,703 characters. There is no Greek, Cyrillic or Devanagari yet, and no Japanese punctuation such as 。.
- It's slow on this CPU: a few seconds per image and up to about 10 seconds for a demo sheet or animation, because every pen step is rasterised separately.

