Community影像github.com

atlasmarkz/handwriting-pdf

將使用者自己的手寫字跡轉換為可重複使用的 TrueType 字型與穩定的設定檔,並以該字型排版任意文字,匯出適合列印的 PDF。完全在本機執行(無網路、無雲端),支援 Windows/macOS/Linux。

handwriting-pdf 是什麼?

此技能讓 AI 代理能夠將使用者提供的單一手寫樣本(照片、練習表或已含手寫字型的 PDF),透過一系列本機指令,轉換為真正的 `.ttf` 字型檔,並以該字型渲染成 PDF 文件。其工作流程涵蓋四種輸入情境:最佳品質的練習表(Flow A)、自由形式照片(Flow B)、既有字型(Flow C),以及直接從 PDF 提取內嵌字型或文字圖層(Flow D)。使用者可以將已建好的字型與排版參數儲存為「設定檔」,以便日後在不同文件或平台上一致地重現相同的手寫風格,同時也提供實驗性的合成引擎,以近似風格填補樣本中未包含的字元。所有處理皆於本機進行,確保資料隱私。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/atlasmarkz/handwriting-pdf/tree/HEAD

Installed? Explore more 影像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

手寫字 → PDF

從手寫樣本建立真實的 .ttf 字型,再用該字型將文字渲染成看起來像書寫者自己手寫的 PDF。所有處理都在本機執行,樣本絕不會離開你的機器。

**需要事先告訴使用者的殘酷事實:**這不是一個能從一張照片虛構出 3000 個中文字元的 AI。字型只能包含樣本中實際寫過的字元。所以:拉丁文字需要約 60–100 個書寫字元;中文字則需要文件中每個不同的字元(幾百個是常態,數千個則不切實際)。缺少的字元會以中性的手寫備用字型繪製並回報,絕不會無聲無息地虛構。

0. 找到工具

技能目錄就是包含這個 SKILL.md 的資料夾。透過其啟動器來呼叫 CLI:

  • Windows:<skill>\bin\hwpdf.cmd <command> ...
  • macOS/Linux:<skill>/bin/hwpdf <command> ...

如果啟動器遺失,請先安裝(Windows 上執行 <skill>\install.ps1,其他平台執行 <skill>/install.sh),或者當相依套件已經可用時,直接執行 python <skill>/scripts/hwpdf.py <command> ...。hwpdf doctor 必須在執行任何其他指令前顯示 status ok;如果沒有,請執行安裝程式並回報相依性錯誤,不要自行即興處理。

1. 選擇輸入流程

情境流程
預設:使用者想要一份使用他們自己手寫的真實文件A. 練習表(最佳品質,全自動的單元格對應)
使用者給你一份已顯示其手寫的 PDFD. PDF 輸入 — 先嘗試內嵌字型,否則從文字圖層收穫字形
使用者已經寄來一張手寫照片,且不想再寫更多B. 自由形式照片(代理需要標記裁剪出的字形)
使用者已經有自己的 .ttf/.otf 字型C. 僅字型 — 跳到步驟 4,然後儲存設定檔

在產生任何東西之前,先詢問文件文字:練習表只需要文件中用到的字元,所以文字簡短,練習表也會簡短。

流程 A — 練習表(推薦)

  1. 將目標文字放入一個 UTF-8 檔案中,例如 hw/doc.txt,然後:
hwpdf template --text-file hw/doc.txt -d hw

這會寫出 hw/template.pdf(以及 hw/template.json)。每頁 30 個單元格,每 30 個不同的字元一張紙。精確地告訴使用者以下事項:

  • 以 100% / 實際大小 列印(絕不「縮放至頁面」);
  • 使用深色筆(0.5 公釐或更粗)描繪每一個淺灰色字形——原子筆太淡了;
  • 保持四個黑色角落方塊可見且未做記號;
  • 從上方以均勻光線拍攝每頁照片,填滿畫面,然後寄送檔案。
  1. 按頁面順序掃描照片:
hwpdf scan hw/page1.jpg hw/page2.jpg -d hw

透視和輕微的旋轉會從角落方塊進行校正。輸出 hw/glyphs.json 和 hw/glyphs/*.png。如果某個單元格回報「缺失」,表示該字形未被書寫或太模糊——請告知是哪個字元,並提供僅針對這些單元格重新拍攝的選項。 3. 建構字型:

hwpdf font -d hw --family "Alex Hand" -o hw/font.ttf
  1. 在進行渲染前,先檢查涵蓋範圍:
hwpdf coverage --font hw/font.ttf --text-file hw/doc.txt

非零的退出碼或有 missing 列表,表示那些字元沒有對應的字形。解決方法:僅為這些字元寫一張小練習表,然後合併進來:

hwpdf template --chars "<missing chars>" -d hw2
hwpdf scan hw2/page1.jpg -d hw --append
hwpdf font -d hw -o hw/font.ttf

否則,接受中性的備用字型,並明確地告知使用者。 5. 渲染:

hwpdf render --font hw/font.ttf --text-file hw/doc.txt -o hw/letter.pdf --size 12 --paper ruled
  1. **查看結果。**將 PDF 頁面渲染為 PNG,並使用視覺能力檢查:
hwpdf preview --pdf hw/letter.pdf -d hw/preview --dpi 150

判斷:筆劃是否太細/太粗?行距是否太擠?字元是否互相碰撞或超出邊界?外觀是否有明顯錯誤?使用 --size、--leading、--jitter、--weight(重建字型)、--paper none|ruled|grid 來修正。

流程 D — 使用者給你一份有手寫的 PDF

當此流程有效時,這是最快的途徑,因為 PDF 已經包含了字形。

  1. 嘗試內嵌字型程式(最佳:完整的字形集,無需重新描繪):
hwpdf extract-font --pdf user.pdf -d hw

好的輸出 = hw/fonts/ 目錄下有一個具有真實字元對應的 .ttf/.otf 檔案(mapped > 20)。 如果報告顯示「subset/cid」,請跳過此步驟。 2. 否則,如果 PDF 有文字圖層(當你可以選取字元時就表示有),從渲染的頁面中收穫字形——文字圖層提供標籤,點陣圖提供墨跡:

hwpdf pdf-specimen --pdf user.pdf -d hw            # 加上 --font-name "<family>" 以只保留他們使用的字型
hwpdf font -d hw --family "Alex Hand" -o hw/font.ttf
  1. 否則就是掃描檔:hwpdf rasterize --pdf user.pdf -d hw/pages → 對頁面影像進行流程 B,或者要求一份練習表(流程 A)。
  2. 將結果儲存為設定檔(下面的步驟 5),然後渲染。

流程 B — 自由形式照片

  1. hwpdf segment hw/photo.jpg -d hw → hw/contact.png(帶編號的縮圖)+ hw/crops/。
  2. 打開 hw/contact.png 並讀取編號。將 hw/labels.json 寫成 {"0":"A","1":"b",...},或者使用 hwpdf label -d hw --pair "0=A 1=B 2=''"("" 表示丟棄該區塊:例如點、污漬、頁面邊緣,或一個分成兩筆畫書寫的字元片段)。
  3. hwpdf font -d hw --labels hw/labels.json -o hw/font.ttf,然後進行上面的步驟 4–6。

連筆草書和多筆畫的中日韓字元使得此流程容易出錯;如果結果看起來不好,請轉換到流程 A 並說明原因。

流程 C — 使用者已有字型

直接跳到 hwpdf coverage 和 hwpdf render,使用 --font <their file>,然後儲存設定檔。

設定檔 — 穩定、可重複使用的方式

設定檔凍結了重現外觀所需的一切:字型檔(複製到設定檔中,並附上 SHA-256 雜湊值)、其預設值,以及一個可直接貼上的提示。

hwpdf profile save --name alex --font hw/font.ttf --source "user's handwriting pdf"
hwpdf profile list
hwpdf render --profile alex --text-file letter.txt -o letter.pdf
  • 設定檔存放在 ~/.handwriting-pdf/profiles/<name>/ 目錄下(包含 profile.json、font.ttf、PROMPT.md);設定 HWPDF_PROFILE_DIR 環境變數可重新定位。
  • PROMPT.md 是為使用者撰寫的:將其貼到任何機器上的任何代理,它就會以相同的版面預設值呼叫相同的字型。
  • 需要反覆調整外觀?一次只改變一個東西——渲染、預覽、比較,然後執行 hwpdf profile save --name alex --font hw/font.ttf --size ... --paper ... 將其設為新的預設值。font --weight 1 會重建一個更粗的筆劃;之後記得重新儲存設定檔,讓變更生效。
  • 從 PDF 建立的設定檔只涵蓋該 PDF 中出現的字元。在承諾能產出完整文件之前,先用 hwpdf coverage --font <profile font> --text-file <new doc> 檢查。

合成 — 使用者從未書寫的字元(實驗性)

一份文件幾乎總是會包含使用者從未寫過的字元;在中文裡這是常態而非例外。有兩種填補方式,按誠實程度排序:

  1. 中性備用字型(預設,可預測):render --fallback auto 會自動選取一個系統手寫字型;頁面會混合使用者的手寫樣式與印刷體或中性的手寫樣式,並且 render 會報告每一個以此種方式繪製的字元。
  2. 合成推斷(hwpdf synth,仍為實驗性):透過借用使用者風格中可測量的部分——傾斜度、筆劃粗細、x 高度、字元寬度——並將這些風格貼到系統骨架字形上,建立一個涵蓋完整字元集的第二個字型。
hwpdf synth doctor                              # 顯示哪些引擎可用,缺了什麼
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   # 先檢查
hwpdf synth verify --font hw/synth.ttf --charset common3500                   # 涵蓋範圍/缺失
hwpdf synth eval --font hw/synth.ttf --real hw/font.ttf -o hw/report.md      # 報告的數值
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                    # 合成字型填補缺口

引擎:stylefit(分析型 — 無需下載、無需 GPU、確定性;中文字元保留系統無襯線骨架,僅擷取使用者的傾斜度和粗細)和 stub(測試用固定裝置,非風格轉換)。擴散引擎 diff-font 需要的權重檔案其授權尚未解決(請見 PLAN.md §8 S4)—— synth doctor 會如實告知,不會假裝可用。

**說明它是什麼:**使用者寫過的字元會被原樣重現;推斷出來的字元則是「他們的傾斜度和粗細,套用於印刷體骨架上」。不要告訴使用者推斷出來的那一半「看起來像他們」。在出貨前,請檢查 <font>.json 中的 meta.gate(rejected 應為 0)並查看樣本。

規則

  1. **僅限本機。**絕不將樣本、字型或輸出檔案上傳;不進行任何 API 呼叫。
  2. **僅限使用者自己的手寫。**拒絕模仿第三方的筆跡、簽名或信紙標頭,並且拒絕產生簽名、合約、證書或官方文件——簡短說明原因(偽造、詐欺、證據規則),並提供一份正常的打字文件作為替代方案。
  3. **絕不捏造品質。**如果字型只有 40 個字形,就說 40。如果備用字型繪製了半頁文字,就據實以告。逐字報告缺少的字元。
  4. **在責怪工具之前,先要求重新拍攝:**模糊、有陰影、角落被裁剪或網格線被遮蓋的照片是最常見的失敗原因。
  5. 保留工作目錄(hw/)——使用者之後可以增加字元並重建字型。

指令參考

指令用途
hwpdf doctor相依性 + 系統字型檢查
hwpdf template --chars "abc" / --text-file doc.txt -d DIR練習表 PDF + 元資料
hwpdf scan IMG... [-d DIR] [--rotate 90] [--append]拍攝的練習表照片 → 字形遮罩(append = 合併到現有工作區)
hwpdf extract-font --pdf in.pdf -d DIR從 PDF 提取內嵌字型(最佳情況:完整的 TTF)
hwpdf pdf-specimen --pdf in.pdf -d DIR [--font-name F]從 PDF 的文字圖層 + 點陣圖收穫已標記的字形
hwpdf rasterize --pdf in.pdf -d DIR [--dpi 300]掃描的 PDF → 頁面 PNG
hwpdf segment IMG... [-d DIR] [--thresh N] [--deskew]自由形式照片 → 區塊 + 連絡表
hwpdf label -d DIR --order "ABC" / --pair "0=A 1=B"將區塊對應到字元
hwpdf font -d DIR [--labels f] [--family NAME] [--weight -2..2] [--smooth 0..2] -o out.ttf建構字型
hwpdf coverage --font f --text-file doc.txt檢查哪些字元缺少
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|path]PDF(--font system:cjk / system:latin = 內建手寫字型,用於當使用者沒有樣本,且只想要一個手寫外觀時)
hwpdf render --profile NAME --text-file doc.txt -o out.pdf使用已儲存設定檔的字型 + 預設值產生 PDF
hwpdf profile save/list/show/remove ...凍結/檢查可重複使用的手寫設定檔(會寫出 PROMPT.md)
hwpdf preview --pdf out.pdf -d DIR [--dpi 150]PDF 頁面 → PNG 供視覺檢查
hwpdf synth doctor / build / specimen / verify / charsets可選的推斷引擎:從書寫子集建立完整字元集字型(請見合成章節)
hwpdf selftest -d DIR [--messy]合成端對端冒煙測試

限制(在相關時說明)

  • 每個字元只有一個字形:沒有連筆草書,沒有不同出現次數之間的自然變化,沒有壓力/墨跡紋理。間距抖動是模擬的,字形形狀則不是。
  • 中日韓字元:字型僅包含書寫過的字元。每頁 30 個單元格;一封 300 字的信需要一份 10 頁的練習表。hwpdf synth build --charset common3500 是捷徑,但推斷出來的中日韓字元是使用者的傾斜度加上系統無襯線骨架,而非他們實際的筆觸。
  • PDF 的文字圖層是真實文字(可搜尋/可複製),使用產生的字型。
  • 照片必須顯示練習表的全部四個黑色角落方塊。

詳細資訊:references/workflow.md · references/troubleshooting.md

相關技能