From c76d82e7e8605f8a39dc7351852dd864abac8eb5 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 6 Aug 2026 22:17:44 -0700 Subject: [PATCH] =?UTF-8?q?feat(optional-skills):=20add=20draw-your-font?= =?UTF-8?q?=20=E2=80=94=20handwriting=20photo=20to=20installable=20font?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../creative/draw-your-font/SKILL.md | 154 ++++++++++++++++ .../references/troubleshooting.md | 51 ++++++ .../docs/reference/optional-skills-catalog.md | 1 + .../creative/creative-draw-your-font.md | 169 ++++++++++++++++++ website/sidebars.ts | 1 + 5 files changed, 376 insertions(+) create mode 100644 optional-skills/creative/draw-your-font/SKILL.md create mode 100644 optional-skills/creative/draw-your-font/references/troubleshooting.md create mode 100644 website/docs/user-guide/skills/optional/creative/creative-draw-your-font.md diff --git a/optional-skills/creative/draw-your-font/SKILL.md b/optional-skills/creative/draw-your-font/SKILL.md new file mode 100644 index 0000000000000..d558b736c949b --- /dev/null +++ b/optional-skills/creative/draw-your-font/SKILL.md @@ -0,0 +1,154 @@ +--- +name: draw-your-font +description: "Turn a photo of handwriting into an installable font (TTF/WOFF)." +version: 0.1.0 +author: Danilo Znamerovszkij (https://github.com/danilo-znamerovszkij/draw-your-font), ported by Hermes Agent +license: MIT +platforms: [linux, macos, windows] +required_commands: [node, npx] +metadata: + hermes: + tags: [font, handwriting, typography, ttf, woff, vision, creative] + category: creative + homepage: https://github.com/danilo-znamerovszkij/draw-your-font + related_skills: [pixel-art] +--- + +# draw-your-font + +Photo of handwritten letters in → installable font out. You do the seeing +(find and label letters, judge quality); the CLI does all geometry (trace, +metrics, font assembly). Never edit SVG paths or coordinates yourself. + +## Setup in Hermes (once per session) + +The CLI is the pinned npm package `draw-your-font@0.1.0` — run it via npx (Node ≥ 18 required, no global install needed): + +```bash +npx -y draw-your-font@0.1.0 --help +``` + +Wherever the examples below show `$DYF`, use `npx -y draw-your-font@0.1.0`. Shell variables do not persist between tool calls, so paste the full command each time. Everything runs locally; the user's handwriting never leaves the machine. + +Photos arrive in Hermes either as a file path in the message or via the gateway image cache — use the actual file path with the CLI. When a photo lands in the conversation with no path, ask the user for the file (the CLI needs a real file, not your memory of the image). + +Do the visual steps (contact sheets, previews, glyph sheets) by loading the PNGs with `vision_analyze`. + +## Decide the flow + +- **User has no photo yet** → offer the template: print, write, photograph. +- **User shares photo(s) of handwriting** → main flow below. +- **User pasted an image but there is no file path** → you can see it, but the + CLI needs a file. Ask them to drag the image file into the terminal (that + inserts its path) or give the path directly. Do not proceed from memory. +- **User wants changes to a font built this session** → Refine section. + +## Template flow (best quality) + +```bash +$DYF template -o template.pdf --charset minimal # or: spanish +``` + +Tell the user: print it, write one character per box with a dark pen +(0.5 mm+), keep the letter sitting on the solid line, then photograph each +page from above in good light and share the file paths. The grid prints in +light grey and vanishes during processing - only their ink survives. + +## Main flow: photo(s) → font + +**1. Segment.** Works for template pages and freeform photos alike: + +```bash +$DYF segment photo1.jpg photo2.jpg -d work +``` + +**2. Look, then label.** Load `work/contact-1.png` with `vision_analyze` (one per photo): every +detected blob is numbered. This is the step where your eyes matter - check: + +- Did every written character get exactly one box? A letter drawn with + separate strokes may appear as two boxes (relabel handles it: give the main + box the character and mark the fragment `""`), and two touching letters may + share one box (ask the user to re-shoot just those, or accept the gap). +- Junk boxes (shadows, ruled lines, smudges, page edges) → label them `""`. + +Then write `work/labels.json` mapping blob id → character, e.g. +`{"0": "A", "1": "B", "7": "", "8": "a"}`: + +- Template page: order is the charset order printed on the template - verify + against the sheet instead of trusting it blindly. minimal order: A–Z, a–z, + 0–9, then `.,;:!?'"-()@#&+/$`; spanish appends `ÑñÁÉÍÓÚáéíóúü¿¡`. +- Freeform: identify each letter from the contact sheet. Uppercase vs + lowercase for shape-twins (S/s, O/o, C/c, X/x…) is decided by relative size + and position - compare against neighbors you're sure of. +- The user told you what they wrote (e.g. "ABC then abc")? Trust it, map in + reading order (top row first, left to right), and verify visually. +- Same letter appears twice → label the better-drawn one, `""` the other. + +**3. Build.** + +```bash +$DYF build -d work --labels work/labels.json --name "Dan's Hand" +``` + +Name the font after the user (ask if unclear - one short question max). + +**4. Judge before delivering.** Load `work/preview.png` and `work/glyphs.png` with `vision_analyze` +and critique like an art director: + +- Broken or blotchy letters (bad trace) → often a faint pen stroke; try + `--weight 1`, or ask for a re-shoot of just that letter. +- Everything too thin/thick → rebuild with `--weight 1` / `--weight -1`. +- Jagged edges → rebuild with `--smooth 1.5` (up to 2). +- A letter placed wrong (e.g. a `g` not descending) → usually a mislabel; + fix labels.json and rebuild. +- Filled-in bowls (b, o, g look solid): should never happen - if it does, + the crop is smudged; ask for a re-shoot. + +Rebuilds are cheap and safe to iterate. Fix what you can yourself first; +only bother the user for re-shoots when the source ink is the problem. + +**5. Deliver.** The font lands at `/.ttf` (the +build output prints the exact path). Give that path and how to install: +macOS - double-click → "Install Font"; Windows - right-click → "Install". +Mention what's missing (the build prints uncovered letters) and offer, +without pushing: + +- Web formats + CSS: rebuild with `--formats ttf,woff,woff2,css`. +- A legibility read (below). +- Their next photo to fill missing characters: re-run segment with ALL + photos (old and new) into a fresh workdir - `$DYF segment p1.jpg p2.jpg -d + work2` - then relabel from the new contact sheets (blob ids renumber; the + old labels.json does not carry over) and build from the new workdir. + +## Refine (conversational iteration) + +| User says | Do | +|---|---| +| "smoother / rounder" | `build … --smooth 1.5` (max 2) | +| "thicker / bolder" | `build … --weight 1` (max 2) | +| "thinner / lighter" | `build … --weight=-1` (negative needs the `=` form) | +| "the g looks bad" | show them `work/crops/.png` for that letter; offer re-shoot or smooth | +| "wrong letter" / swap | edit labels.json, rebuild | +| "give me woff2 / web" | `build … --formats ttf,woff,woff2,css` | +| custom preview text | `$DYF preview -d work --text "…"` (after a build) | + +All refine commands rebuild from the stored crops - no re-photographing +needed unless the ink itself is the problem. + +## Legibility report (offer after delivering) + +```bash +$DYF preview -d work --text "minimum mill rn m cl d I l 1 O 0 quick brown fox" -o work/legibility.png +``` + +Read it and give an honest, kind read: a score out of 10 for body-text use, +the 2–3 letter pairs most likely to confuse (rn→m, cl→d, I/l/1, O/0), and one +or two concrete fixes (rewrite those letters larger, more spacing). Note that +display use (headings, notes) is more forgiving than paragraphs. Never gate +delivery on this - it's advice, not a blocker. + +## Troubleshooting + +Segmentation found far too many / too few blobs, grey guide lines surviving, +shadow blobs, faint ballpoint strokes → see +`references/troubleshooting.md`. diff --git a/optional-skills/creative/draw-your-font/references/troubleshooting.md b/optional-skills/creative/draw-your-font/references/troubleshooting.md new file mode 100644 index 0000000000000..cb4dddb4a59cf --- /dev/null +++ b/optional-skills/creative/draw-your-font/references/troubleshooting.md @@ -0,0 +1,51 @@ +# Troubleshooting capture & segmentation + +The binarizer is adaptive (local background estimate) with two knobs on +`segment`/`make`: + +- `--delta N` (default 40): how much darker than the local paper a pixel must + be to count as ink. Lower = more sensitive (catches faint pens, also more + noise). Raise to 55–70 for photos with heavy shadows misread as ink. +- `--cap N` (default 165): absolute grey ceiling for ink after contrast + normalization. Anything lighter is never ink - this is what erases the + template's grey guides. Lower to 140 if printed guides survive into blobs; + raise to 190 for a very faint pencil (expect more noise). + +Re-running segment rewrites blobs.json and renumbers every blob - discard +any labels.json written earlier and relabel from the fresh contact sheet +(prefer a fresh `-d` workdir). + +## Symptoms → fixes + +**Hundreds of tiny blobs** - noisy paper texture or aggressive delta. Re-run +segment with `--delta 55`. If the photo is low light, ask for a brighter shot. + +**A huge blob spanning the page** - a shadow edge or the page border got +thresholded. Crop the photo to just the paper (or re-shoot from directly +above), or raise `--delta`. + +**Letters missing entirely** - pen too faint (pencil, gel on glossy paper). +Try `--delta 25 --cap 190`. If still missing, the honest fix is rewriting +with a darker pen; say so. + +**Strokes broken into fragments** - thin ballpoint. Try `--delta 30`, then +`build --weight 1` to fatten what traced. Recommend a 0.5mm+ pen for the +re-shoot. + +**Two letters in one box** - they touch on paper. No code fix; ask the user +to re-write just those letters with space between them, segment the new +photo, and merge via labels. + +**Template guides appear as blobs** - printer printed the grey too dark. +Re-run with `--cap 140`. If their printer only does solid black, they can +still use the template - the guides will show as long thin blobs; label them +all `""`. + +**i/j dots detached as separate blobs** - normally auto-merged; if the dot is +very far from the stem it may not be. Label the stem blob with the letter and +the dot `""` - or better, relabel both after a re-shoot. (A dotless i still +reads fine in most handwriting.) + +**Rotated/skewed photo** - mild angles are fine and become part of the font's +character. A strongly rotated photo (>5°) will slant every glyph; ask for a +straighter shot rather than trying to compensate. diff --git a/website/docs/reference/optional-skills-catalog.md b/website/docs/reference/optional-skills-catalog.md index a617d2d84886a..7f2d71267ddde 100644 --- a/website/docs/reference/optional-skills-catalog.md +++ b/website/docs/reference/optional-skills-catalog.md @@ -61,6 +61,7 @@ hermes skills uninstall | [**blender-mcp**](/docs/user-guide/skills/optional/creative/creative-blender-mcp) | Drive Blender via the catalog blender MCP, with bpy recipes. | | [**concept-diagrams**](/docs/user-guide/skills/optional/creative/creative-concept-diagrams) | Generate flat, minimal educational SVG visuals as HTML. | | [**creative-ideation**](/docs/user-guide/skills/optional/creative/creative-creative-ideation) | Generate ideas via named methods from creative practice. | +| [**draw-your-font**](/docs/user-guide/skills/optional/creative/creative-draw-your-font) | Turn a photo of handwriting into an installable font (TTF/WOFF). | | [**heartmula**](/docs/user-guide/skills/optional/creative/creative-heartmula) | HeartMuLa: Suno-like song generation from lyrics + tags. | | [**hyperframes**](/docs/user-guide/skills/optional/creative/creative-hyperframes) | Render MP4/WebM videos from HTML compositions. | | [**kanban-video-orchestrator**](/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator) | Plan and run multi-agent video production pipelines. | diff --git a/website/docs/user-guide/skills/optional/creative/creative-draw-your-font.md b/website/docs/user-guide/skills/optional/creative/creative-draw-your-font.md new file mode 100644 index 0000000000000..23a0596bc8ce5 --- /dev/null +++ b/website/docs/user-guide/skills/optional/creative/creative-draw-your-font.md @@ -0,0 +1,169 @@ +--- +title: "Draw Your Font — Turn a photo of handwriting into an installable font (TTF/WOFF)" +sidebar_label: "Draw Your Font" +description: "Turn a photo of handwriting into an installable font (TTF/WOFF)" +--- + +{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} + +# Draw Your Font + +Turn a photo of handwriting into an installable font (TTF/WOFF). + +## Skill metadata + +| | | +|---|---| +| Source | Optional — install with `hermes skills install official/creative/draw-your-font` | +| Path | `optional-skills/creative/draw-your-font` | +| Version | `0.1.0` | +| Author | Danilo Znamerovszkij (https://github.com/danilo-znamerovszkij/draw-your-font), ported by Hermes Agent | +| License | MIT | +| Platforms | linux, macos, windows | +| Tags | `font`, `handwriting`, `typography`, `ttf`, `woff`, `vision`, `creative` | +| Related skills | [`pixel-art`](/docs/user-guide/skills/optional/creative/creative-pixel-art) | + +## Reference: full SKILL.md + +:::info +The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active. +::: + +# draw-your-font + +Photo of handwritten letters in → installable font out. You do the seeing +(find and label letters, judge quality); the CLI does all geometry (trace, +metrics, font assembly). Never edit SVG paths or coordinates yourself. + +## Setup in Hermes (once per session) + +The CLI is the pinned npm package `draw-your-font@0.1.0` — run it via npx (Node ≥ 18 required, no global install needed): + +```bash +npx -y draw-your-font@0.1.0 --help +``` + +Wherever the examples below show `$DYF`, use `npx -y draw-your-font@0.1.0`. Shell variables do not persist between tool calls, so paste the full command each time. Everything runs locally; the user's handwriting never leaves the machine. + +Photos arrive in Hermes either as a file path in the message or via the gateway image cache — use the actual file path with the CLI. When a photo lands in the conversation with no path, ask the user for the file (the CLI needs a real file, not your memory of the image). + +Do the visual steps (contact sheets, previews, glyph sheets) by loading the PNGs with `vision_analyze`. + +## Decide the flow + +- **User has no photo yet** → offer the template: print, write, photograph. +- **User shares photo(s) of handwriting** → main flow below. +- **User pasted an image but there is no file path** → you can see it, but the + CLI needs a file. Ask them to drag the image file into the terminal (that + inserts its path) or give the path directly. Do not proceed from memory. +- **User wants changes to a font built this session** → Refine section. + +## Template flow (best quality) + +```bash +$DYF template -o template.pdf --charset minimal # or: spanish +``` + +Tell the user: print it, write one character per box with a dark pen +(0.5 mm+), keep the letter sitting on the solid line, then photograph each +page from above in good light and share the file paths. The grid prints in +light grey and vanishes during processing - only their ink survives. + +## Main flow: photo(s) → font + +**1. Segment.** Works for template pages and freeform photos alike: + +```bash +$DYF segment photo1.jpg photo2.jpg -d work +``` + +**2. Look, then label.** Load `work/contact-1.png` with `vision_analyze` (one per photo): every +detected blob is numbered. This is the step where your eyes matter - check: + +- Did every written character get exactly one box? A letter drawn with + separate strokes may appear as two boxes (relabel handles it: give the main + box the character and mark the fragment `""`), and two touching letters may + share one box (ask the user to re-shoot just those, or accept the gap). +- Junk boxes (shadows, ruled lines, smudges, page edges) → label them `""`. + +Then write `work/labels.json` mapping blob id → character, e.g. +`{"0": "A", "1": "B", "7": "", "8": "a"}`: + +- Template page: order is the charset order printed on the template - verify + against the sheet instead of trusting it blindly. minimal order: A–Z, a–z, + 0–9, then `.,;:!?'"-()@#&+/$`; spanish appends `ÑñÁÉÍÓÚáéíóúü¿¡`. +- Freeform: identify each letter from the contact sheet. Uppercase vs + lowercase for shape-twins (S/s, O/o, C/c, X/x…) is decided by relative size + and position - compare against neighbors you're sure of. +- The user told you what they wrote (e.g. "ABC then abc")? Trust it, map in + reading order (top row first, left to right), and verify visually. +- Same letter appears twice → label the better-drawn one, `""` the other. + +**3. Build.** + +```bash +$DYF build -d work --labels work/labels.json --name "Dan's Hand" +``` + +Name the font after the user (ask if unclear - one short question max). + +**4. Judge before delivering.** Load `work/preview.png` and `work/glyphs.png` with `vision_analyze` +and critique like an art director: + +- Broken or blotchy letters (bad trace) → often a faint pen stroke; try + `--weight 1`, or ask for a re-shoot of just that letter. +- Everything too thin/thick → rebuild with `--weight 1` / `--weight -1`. +- Jagged edges → rebuild with `--smooth 1.5` (up to 2). +- A letter placed wrong (e.g. a `g` not descending) → usually a mislabel; + fix labels.json and rebuild. +- Filled-in bowls (b, o, g look solid): should never happen - if it does, + the crop is smudged; ask for a re-shoot. + +Rebuilds are cheap and safe to iterate. Fix what you can yourself first; +only bother the user for re-shoots when the source ink is the problem. + +**5. Deliver.** The font lands at `/.ttf` (the +build output prints the exact path). Give that path and how to install: +macOS - double-click → "Install Font"; Windows - right-click → "Install". +Mention what's missing (the build prints uncovered letters) and offer, +without pushing: + +- Web formats + CSS: rebuild with `--formats ttf,woff,woff2,css`. +- A legibility read (below). +- Their next photo to fill missing characters: re-run segment with ALL + photos (old and new) into a fresh workdir - `$DYF segment p1.jpg p2.jpg -d + work2` - then relabel from the new contact sheets (blob ids renumber; the + old labels.json does not carry over) and build from the new workdir. + +## Refine (conversational iteration) + +| User says | Do | +|---|---| +| "smoother / rounder" | `build … --smooth 1.5` (max 2) | +| "thicker / bolder" | `build … --weight 1` (max 2) | +| "thinner / lighter" | `build … --weight=-1` (negative needs the `=` form) | +| "the g looks bad" | show them `work/crops/.png` for that letter; offer re-shoot or smooth | +| "wrong letter" / swap | edit labels.json, rebuild | +| "give me woff2 / web" | `build … --formats ttf,woff,woff2,css` | +| custom preview text | `$DYF preview -d work --text "…"` (after a build) | + +All refine commands rebuild from the stored crops - no re-photographing +needed unless the ink itself is the problem. + +## Legibility report (offer after delivering) + +```bash +$DYF preview -d work --text "minimum mill rn m cl d I l 1 O 0 quick brown fox" -o work/legibility.png +``` + +Read it and give an honest, kind read: a score out of 10 for body-text use, +the 2–3 letter pairs most likely to confuse (rn→m, cl→d, I/l/1, O/0), and one +or two concrete fixes (rewrite those letters larger, more spacing). Note that +display use (headings, notes) is more forgiving than paragraphs. Never gate +delivery on this - it's advice, not a blocker. + +## Troubleshooting + +Segmentation found far too many / too few blobs, grey guide lines surviving, +shadow blobs, faint ballpoint strokes → see +`references/troubleshooting.md`. diff --git a/website/sidebars.ts b/website/sidebars.ts index 1db70ac9c49fa..a18e5be313533 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -371,6 +371,7 @@ const sidebars: SidebarsConfig = { 'user-guide/skills/optional/creative/creative-blender-mcp', 'user-guide/skills/optional/creative/creative-concept-diagrams', 'user-guide/skills/optional/creative/creative-creative-ideation', + 'user-guide/skills/optional/creative/creative-draw-your-font', 'user-guide/skills/optional/creative/creative-heartmula', 'user-guide/skills/optional/creative/creative-hyperframes', 'user-guide/skills/optional/creative/creative-kanban-video-orchestrator',