Écriture manuscrite → PDF
Construisez un vrai fichier .ttf à partir d'un échantillon d'écriture manuscrite, puis rendez du texte avec cette police dans un PDF qui ressemble à l'écriture de l'auteur. Tout s'exécute localement ; l'échantillon ne quitte jamais la machine.
Vérité difficile à dire à l'utilisateur d'emblée : ce n'est pas une IA qui invente 3 000 glyphes chinois à partir d'une seule photo. Une police ne peut contenir que les caractères réellement écrits sur l'échantillon. Donc : le texte latin nécessite ~60 à 100 caractères écrits ; le texte chinois nécessite chaque caractère distinct du document (quelques centaines est normal, des milliers est irréaliste). Les caractères manquants sont dessinés avec un fallback neutre d'écriture manuscrite et signalés — jamais inventés en silence.
0. Localiser l'outil
Le répertoire du skill est le dossier contenant ce fichier SKILL.md. Appelez l'interface en ligne de commande via son lanceur :
- Windows :
<skill>\bin\hwpdf.cmd <commande> ... - macOS/Linux :
<skill>/bin/hwpdf <commande> ...
Si le lanceur est manquant, installez d'abord (<skill>\install.ps1 sous Windows, <skill>/install.sh ailleurs), ou exécutez python <skill>/scripts/hwpdf.py <commande> ... lorsque les dépendances sont déjà disponibles. hwpdf doctor doit afficher status ok avant toute autre chose ; si ce n'est pas le cas, exécutez l'installateur et signalez l'erreur de dépendance au lieu d'improviser.
1. Choisir le flux d'entrée
| Situation | Flux |
|---|---|
| Par défaut : l'utilisateur souhaite un vrai document dans son écriture | A. Feuille d'exercice (meilleure qualité, cartographie automatique des cellules) |
| L'utilisateur vous remet un PDF qui montre déjà son écriture | D. Réception PDF — essayez d'abord la police intégrée, sinon récoltez les glyphes depuis la couche de texte |
| L'utilisateur a déjà envoyé une photo de son écriture et ne veut pas en écrire plus | B. Photo libre (l'agent étiquette les glyphes découpés) |
L'utilisateur a déjà son propre fichier .ttf/.otf | C. Police uniquement — passez à l'étape 4, puis enregistrez un profil |
Demandez le texte du document avant de générer quoi que ce soit : la feuille d'exercice n'a besoin que des caractères que le document utilise, donc un texte court signifie une feuille courte.
Flux A — feuille d'exercice (recommandé)
- Placez le texte cible dans un fichier UTF-8, par ex.
hw/doc.txt, puis :
Cela écrithwpdf template --text-file hw/doc.txt -d hwhw/template.pdf(ethw/template.json). 30 cellules par page, une page pour 30 caractères distincts. Dites exactement ceci à l'utilisateur :- imprimez à 100 % / Taille réelle (jamais "ajuster à la page") ;
- tracez chaque glyphe gris clair avec un stylo foncé (0,5 mm ou plus épais) — un stylo à bille est trop clair ;
- gardez les quatre carrés noirs des coins visibles et non marqués ;
- photographiez chaque page de dessus avec une lumière uniforme, remplissez le cadre et envoyez les fichiers.
- Scannez les photos dans l'ordre des pages :
La perspective et les petites rotations sont corrigées à partir des carrés de coin. Sortiehwpdf scan hw/page1.jpg hw/page2.jpg -d hwhw/glyphs.jsonethw/glyphs/*.png. Si une cellule revient comme "manquante", le glyphe n'a pas été écrit ou était trop pâle — dites quels caractères et proposez une reprise photo de ces cellules uniquement. - Construisez la police :
hwpdf font -d hw --family "Alex Hand" -o hw/font.ttf - Vérifiez la couverture avant le rendu :
Une sortie non nulle / listehwpdf coverage --font hw/font.ttf --text-file hw/doc.txtmissingsignifie que ces caractères n'ont pas de glyphe. Corrigez en écrivant une petite deuxième feuille pour ces seuls caractères et en la fusionnant :
Sinon, acceptez le fallback neutre et dites-le explicitement.hwpdf template --chars "<caractères manquants>" -d hw2 hwpdf scan hw2/page1.jpg -d hw --append hwpdf font -d hw -o hw/font.ttf - Rendu :
hwpdf render --font hw/font.ttf --text-file hw/doc.txt -o hw/letter.pdf --size 12 --paper ruled - Regardez le résultat. Rendez les pages en PNG et inspectez-les avec la vision :
Jugez : les traits sont-ils trop fins/épais, les lignes trop serrées, les caractères entrent-ils en collision ou débordent-ils des marges, quelque chose semble-t-il clairement faux ? Corrigez avechwpdf preview --pdf hw/letter.pdf -d hw/preview --dpi 150--size,--leading,--jitter,--weight(reconstruisez la police),--paper none|ruled|grid.
Flux D — l'utilisateur vous remet un PDF avec son écriture
C'est le chemin le plus rapide quand cela fonctionne, car le PDF contient déjà les formes.
- Essayez le programme d'extraction de police intégré (meilleur : jeu de glyphes complet, pas de retraçage) :
Bonne sortie = un fichierhwpdf extract-font --pdf user.pdf -d hw.ttf/.otfdanshw/fonts/avec une table de caractères réelle (mapped> 20). Ignorez si le rapport dit "subset/cid". - Sinon, si le PDF a une couche de texte (c'est le cas quand vous pouvez sélectionner les caractères), récoltez les glyphes depuis la page rendue — la couche de texte donne l'étiquette, le raster donne l'encre :
hwpdf pdf-specimen --pdf user.pdf -d hw # ajoutez --font-name "<famille>" pour ne conserver que leur police hwpdf font -d hw --family "Alex Hand" -o hw/font.ttf - Sinon, c'est un scan :
hwpdf rasterize --pdf user.pdf -d hw/pages→ Flux B sur les images de page, ou demandez une feuille d'exercice (Flux A). - Enregistrez le résultat comme profil (étape 5 ci-dessous), puis effectuez le rendu.
Flux B — photo libre
hwpdf segment hw/photo.jpg -d hw→hw/contact.png(vignettes numérotées) +hw/crops/.- Ouvrez
hw/contact.pnget lisez les numéros. Écrivezhw/labels.jsoncomme{"0":"A","1":"b",...}, ou utilisezhwpdf label -d hw --pair "0=A 1=B 2=''"(""supprime un blob : points, taches, bords de page, ou fragment d'une lettre dessinée en deux traits). hwpdf font -d hw --labels hw/labels.json -o hw/font.ttf, puis étapes 4 à 6 ci-dessus.
L'écriture liée/cursive et les caractères CJK à plusieurs traits rendent ce flux sujet aux erreurs ; si le résultat est mauvais, passez au Flux A et expliquez pourquoi.
Flux C — l'utilisateur a déjà une police
Passez directement à hwpdf coverage et hwpdf render avec --font <leur fichier>, puis enregistrez un profil.
Profils — la méthode stable et réutilisable
Un profil fige tout ce qui est nécessaire pour reproduire l'apparence : le fichier de police (copié dans le profil, avec SHA-256), ses paramètres par défaut, et une invite prête à coller.
wpdf profile save --name alex --font hw/font.ttf --source "pdf de l'écriture de l'utilisateur"
hwpdf profile list
hwpdf render --profile alex --text-file letter.txt -o letter.pdf
- Les profils résident dans
~/.handwriting-pdf/profiles/<nom>/(profile.json,font.ttf,PROMPT.md) ; définissezHWPDF_PROFILE_DIRpour les déplacer. PROMPT.mdest écrit pour l'utilisateur : collez-le dans n'importe quel agent sur n'importe quelle machine et il appellera la même police avec les mêmes paramètres de mise en page par défaut.- Vous itérez sur l'apparence ? Changez une chose à la fois — rendez, prévisualisez, comparez, puis
hwpdf profile save --name alex --font hw/font.ttf --size ... --paper ...pour en faire le nouveau défaut.font --weight 1reconstruit un trait plus gras ; réenregistrez le profil ensuite pour que le changement persiste. - Un profil construit à partir d'un PDF ne couvre que les caractères qui apparaissent dans ce PDF. Vérifiez avec
hwpdf coverage --font <police du profil> --text-file <nouveau doc>avant de promettre un document complet.
Synthèse — caractères que l'utilisateur n'a jamais écrits (expérimental)
Un document a presque toujours besoin de caractères que l'utilisateur n'a jamais écrits ; en chinois, c'est la norme, pas l'exception. Deux façons de les combler, par ordre d'honnêteté :
- Fallback neutre (par défaut, prévisible) :
render --fallback autochoisit une police d'écriture manuscrite système ; la page mélange leur écriture avec une écriture imprimée ou neutre, etrenderrapporte chaque caractère dessiné de cette façon. - Inférence par synthèse (
hwpdf synth, encore expérimental) : construisez une seconde police qui couvre le jeu de caractères complet en empruntant les parties mesurables de leur style — inclinaison, épaisseur de trait, hauteur d'x, largeur de glyphe — et en les appliquant à un glyphe squelette système.
wpdf synth doctor # quels moteurs sont utilisables, ce qui manque
hwpdf synth build --style hw/font.ttf --charset common3500 -o hw/synth.ttf
hwpdf synth specimen --font hw/synth.ttf --real hw/font.ttf -o hw/sheet.png # inspectez d'abord
hwpdf synth verify --font hw/synth.ttf --charset common3500 # couverture / manquant
hwpdf synth eval --font hw/synth.ttf --real hw/font.ttf -o hw/report.md # chiffres pour le rapport
hwpdf profile save --name alex --font hw/font.ttf --synth-font hw/synth.ttf
hwpdf render --profile alex --text-file doc.txt -o out.pdf # la synthèse comble les lacunes
Moteurs : stylefit (analytique — pas de téléchargement, pas de GPU, déterministe ; les glyphes chinois conservent un squelette sans empattement système et ne reprennent que l'inclinaison/l'épaisseur de l'utilisateur) et stub (dispositif de test, pas de transfert de style). Le moteur de diffusion diff-font nécessite des poids dont les licences ne sont pas résolues (PLAN.md §8 S4) — synth doctor le dit plutôt que de faire semblant.
Dites ce que c'est : les caractères qu'ils ont écrits sont reproduits textuellement ; les caractères inférés sont "leur inclinaison et leur épaisseur sur un squelette imprimé". Ne dites pas à l'utilisateur que la moitié inférée "lui ressemble". Vérifiez meta.gate dans <police>.json (rejected doit être 0) et regardez le spécimen avant d'expédier.
Règles
- Local uniquement. Ne téléchargez jamais l'échantillon, la police ou la sortie ; aucun appel API.
- Uniquement l'écriture manuscrite de l'utilisateur. Refusez d'imiter l'écriture manuscrite, la signature ou l'en-tête de lettre d'un tiers, et refusez la génération de signature / contrat / certificat / document officiel — expliquez brièvement (contrefaçon, fraude, règles de preuve) et proposez un document dactylographié normal à la place.
- Ne fabriquez jamais la qualité. Si la police a 40 glyphes, dites 40. Si le fallback a dessiné la moitié de la page, dites-le. Signalez les caractères manquants textuellement.
- Demandez une reprise photo avant d'accuser l'outil : les photos floues, ombrées, avec des coins coupés ou des lignes de grille couvertes sont la cause d'échec la plus courante.
- Conservez le répertoire de travail (
hw/) — l'utilisateur peut ajouter des caractères plus tard et reconstruire la police.
Référence des commandes
| Commande | Objectif |
|---|---|
hwpdf doctor | vérification des dépendances + polices système |
hwpdf template --chars "abc" / --text-file doc.txt -d DIR | PDF de feuille d'exercice + métadonnées |
hwpdf scan IMG... [-d DIR] [--rotate 90] [--append] | feuille photographiée → masques de glyphes (append = fusionne dans le travail existant) |
hwpdf extract-font --pdf in.pdf -d DIR | extraire les polices intégrées d'un PDF (meilleur cas : TTF complet) |
hwpdf pdf-specimen --pdf in.pdf -d DIR [--font-name F] | récolter les glyphes étiquetés depuis la couche de texte + raster d'un PDF |
hwpdf rasterize --pdf in.pdf -d DIR [--dpi 300] | PDF scanné → PNG de page |
hwpdf segment IMG... [-d DIR] [--thresh N] [--deskew] | photo libre → blobs + planche contact |
hwpdf label -d DIR --order "ABC" / --pair "0=A 1=B" | mapper les blobs aux caractères |
hwpdf font -d DIR [--labels f] [--family NOM] [--weight -2..2] [--smooth 0..2] -o out.ttf | construire la police |
hwpdf coverage --font f --text-file doc.txt | quels caractères sont manquants |
| `hwpdf render --font f --text-file doc.txt -o out.pdf [--size 12] [--leading 1.8] [--paper ruled] [--jitter 1] [--ink "#1a1c24"] [--fallback auto | none |
hwpdf render --profile NOM --text-file doc.txt -o out.pdf | PDF utilisant la police + paramètres d'un profil enregistré |
hwpdf profile save/list/show/remove ... | geler / inspecter le profil d'écriture manuscrite réutilisable (écrit PROMPT.md) |
hwpdf preview --pdf out.pdf -d DIR [--dpi 150] | pages PDF → PNG pour inspection visuelle |
hwpdf synth doctor / build / specimen / verify / charsets | moteur d'inférence optionnel : police de jeu de caractères complet à partir d'un sous-ensemble écrit (voir la section Synthèse) |
hwpdf selftest -d DIR [--messy] | test de fumée synthétique de bout en bout |
Limites (mentionnez-les quand pertinent)
- Un glyphe par caractère : pas de cursive liée, pas de variation naturelle entre occurrences, pas de texture de pression/encre. La variation d'espacement est simulée, les formes de glyphes ne le sont pas.
- CJK : la police ne contient que les caractères écrits. 30 cellules par page ; une lettre de 300 caractères nécessite une feuille d'exercice de 10 pages.
hwpdf synth build --charset common3500est le raccourci, mais le CJK inféré est un squelette sans empattement système dans l'inclinaison de l'utilisateur, pas son travail de pinceau réel. - La couche de texte du PDF est du texte réel (consultable/copiable) dans la police générée.
- Les photos doivent montrer les quatre carrés de coin noirs de la feuille d'exercice.
Détails : references/workflow.md · references/troubleshooting.md