Skip to content

feat: checkbox 勾選的字形覆蓋指引/偵測 —— ☑ 在 CJK 字型表單經 emoji fallback 走樣,官方慣例是 □→■ #189

Description

@kiki830621

Problem

Original text(使用者,2026-08-21,附截圖):
「他打勾勾不是用原本的格式,你需要辨認原本的格式然後取代成黑色框框,字體也要完全一樣。這代表改動必須要是『維持格式的』(或者這是che-word-mcp的工作)」

replace_text 把表單的 (U+25A1)換成 (U+2611)勾選時,視覺結果與表單原字體完全不一致 渲染成灰底圓角的彩色 emoji 樣式,而非表單細線框的文字字形。

Type

feature

根因(已查明,非 run 格式遺失)

Run 層格式保留(同一 run 內替換字元,字型宣告未變)。問題在字形覆蓋
表單常用的 CJK 字型(新細明體、標楷體等)有 U+25A1(□)與 U+25A0(■)的字形,
沒有 U+2611(☑)——渲染器(Word/macOS 預覽/LibreOffice 轉 PDF)對缺字形的
字元做 font fallback,落到 Apple Color Emoji 之類的 emoji 字型,於是勾選框整顆變成
emoji 樣式。宣告的字型沒變,實際渲染的字型變了——這是「格式保持」在字元層級的盲區。

實測對照(台灣官方表單的正確慣例)

某 2021–2024 完整 REC 送審前例的已填申請書(兩個版本一致):

□ U+25A1 × 94(未勾選)
■ U+25A0 × 68(勾選)
☑ U+2611 × 0

台灣公文慣例的勾選是 (同區塊、同字型覆蓋、永不 fallback),不是

Expected(擇一或皆做;工具邊界判斷見下)

  1. 文件層replace_text 工具描述加一段字元選擇指引——在 CJK 字型表單中做 checkbox
    勾選時用 ,勿用 (emoji fallback 風險)
  2. 工具層:新增 toggle_checkbox 類 helper(或 replace_text 加警告)——當插入字元
    在該 run 宣告字型的 cmap 中無字形時,回傳 warning(「inserted char may render via
    font fallback」),讓呼叫端及早發現

工具邊界(使用者原話問「或者這是 macdoc 的工作」)

判斷:兩層都不是嚴格意義的 bug——字元選擇是呼叫端的責任,emoji fallback 是渲染器
行為。但「插入字元 vs run 字型覆蓋」的偵測能力放 che-word-mcp 最合理(它持有 run 的
字型宣告與編輯入口);macdoc 層若日後提供字型 cmap 查詢,本 feature 可下沉。先立於此。

Impact

表單代填自動化的產出「文字內容全對、視覺完全不對」——文字層驗證(get_tables 逐 cell
比對)抓不到,只有人眼開檔才會發現。與 #185(vMerge)同屬「文字層驗證的盲區」家族:
#185 盲的是合併拓樸,本案盲的是渲染字形。

與同 session 三案的關係

#185(save 剝 vMerge)、#187(空白 run 比對)、#188(巢狀表定址)之後的第四個發現,
合起來覆蓋寫入、比對、定址、渲染四條路徑。


Current Status

Phase: needs-fix
Last updated: 2026-08-22 by idd-verify (auto-update)

Key Decisions

  • Verify FAIL(新):3 blocking 未解,unattended 的 2 輪自動修復上限已用盡。詳見 PR feat: tick-character guidance + three-valued glyph-coverage probe #193 的 verify report。
  • 三條 blocking 指向同一個未定契約(新)declaredFont 到底是什麼——只接受 OOXML family?也接受 full / PostScript name?本機化名稱在任意語系下如何判定等價?量測的 face 要不要跟 run 的 bold/italic traits?這是被跳過的 Plan approval gate 該由人拍板的事,未在 unattended 下單方裁定。
  • 跨模型驗證兩輪各推翻 coordinator 一次(新):round 1 的「descriptor 比對是精確的」被 System Font → .SF NS 反例推翻;round 2 的「本機化名稱已修好」被英文語系實測推翻(標楷體 的 localized family 回 DFKai-SB,不在名稱集合內)。兩次同病:拿單一機器樣本當通則。
  • Round 1 六項修正中 b/c/d/f 四項經跨模型複核成立;a 不完整、e 部分。
  • D1(文件字元指引)三項要求皆 FULLY addressed,未受 blocking 影響。
  • D3(接線到呼叫端)仍刻意未做,且與 tool 回傳沒有 advisory 通道 —— 非致命警告只寫 stderr,呼叫端永遠看不到 (sister concern from #189) #192 的阻塞關係不變。

Scope Changes

Blocking

  • B1CTFontCopyLocalizedName 只回目前語言偏好的單一名稱,非完整名稱表 → 英文語系下已安裝字型被誤判為 substitution。
  • B2:查詢用 family attribute、驗收卻允許 family/full/PostScript 任一相等,跨命名空間碰撞仍可接受不同家族。
  • B3resolvedFont: 只帶 family,未識別實際量測的 face;同 family 不同 face 的 cmap 不保證相同,且查詢未帶 run traits。
  • tool 回傳沒有 advisory 通道 —— 非致命警告只寫 stderr,呼叫端永遠看不到 (sister concern from #189) #192 仍是 D3 選項 (a) 的前置阻塞。
  • release 組態未驗swift build -c release 兩次皆未跑完,發版前必驗。

Commits

  • 1309687 feat: three-valued glyph-coverage probe for declared fonts
  • ba02f88 feat: tell replace_text callers which tick character survives rendering
  • 7b68a35 docs: record the tick-character guidance and glyph probe
  • 073af55 feat: refuse a glyph verdict about a font nobody declared

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions