# 图形绘制流程(SVG / Mermaid) > **范围**:本仓库文档(`docs/`)里的技术配图——协议帧 / 字节布局、分层架构、依赖 / 就绪屏障、流程 / 时序 / 状态机等。 > **目标**:统一绘图方法与工具链,保证图形**精确、可复现、可 diff、可过 pre-commit**,并与既有 `tools/arch_diagram/` 生成器一致。 > **沉淀**:本流程已沉淀为 `draw-diagram` skill(`.dsh/skills/draw-diagram/SKILL.md`)——画图时直接加载该 skill 即可。 > **产物目录**:生成的 `.svg` 统一放 **`docs/images/`**(专门配图目录,产物入库)。 --- ## 一、选型:什么图用什么工具 | 图形类型 | 工具 | 说明 | |---|---|---| | 协议帧 / 字节布局(精确比例) | **SVG**(`gen_frame_svg.py`) | 字段宽须严格 ∝ 字节数 + 逐字段标注 + 偏移标尺 | | 闪存 / 内存分区布局(精确比例) | **SVG**(`gen_partition_svg.py`) | 帧图生成器的 MB 计量副本(分区宽 ∝ MB 数 + 偏移标尺) | | 端到端链路鸟瞰(一条数据走到底) | **SVG**(`gen_arch_endtoend_svg.py`) | 42 框 37 边、长边各占一条独占通道;标签白片必须落在框间通道内,否则被后画的节点吃掉半字 → 判据见 **`draw-diagram` skill** §三b | | 分层架构 / 模块依赖 | **SVG**(`gen_arch_svg.py`) | 多节点跨层依赖,Mermaid 会画成"意大利面",手工排布更清晰;单层单职责的栈图用其副本 `gen_storage_stack_svg.py` | | 就绪屏障 / 生产者-消费者 | **SVG**(`gen_barrier_svg.py`) | 三栏对齐 + 正交连线,避免交叉 | | 流程图 / 时序 / 状态机 / ER | **Mermaid**(Markdown 内嵌) | 拓扑关系类图,节点少、强调连接;渲染器原生支持 | | UI 界面 / 像素级样机 | `simulator/` 截图 | 非本流程范围 | **为什么"精确布局图"用 SVG,不用 Mermaid / HTML:** | 维度 | SVG | Mermaid | HTML | |---|---|---|---| | 字段宽 ∝ 字节数 | ✅ 像素精确定位 | ❌ 盒子按文本自适应 | ⚠️ 可但繁琐 | | 连续字节流(无假箭头) | ✅ 分段矩形 | ❌ 自动加有向边 | ✅ | | 纯文本(可 diff / lint / pre-commit) | ✅ | ✅(代码块) | ⚠️ | | 直接是图片(免截图) | ✅ | ⚠️ 需渲染器 | ❌ 需截图 | | 矢量无损(任意 DPI) | ✅ | ✅(渲染后) | ⚠️ | | 依赖 | 无(浏览器用系统字体渲染) | 渲染器 | 浏览器 | > 结论:**要精确像素 / 比例的布局图 → SVG 生成器**;**只表达拓扑关系的图 → Mermaid**。 --- ## 二、既有工具(`tools/arch_diagram/`) `tools/arch_diagram/` 下的 26 个生成器共享同一套约定(§3.2),均为**纯标准库**拼 SVG。**逐脚本 / 逐图的 清单不在本文**——2026-10-30 起并成一张,落 **`tools/arch_diagram/README.md`「产物清单」**:32 张入库 `docs/images/*.svg` 逐张列出「谁生成它 / 它答什么问题 / 改哪段数据能重跑 / 被哪篇文档内嵌」,本文一度 另立一张三列表,结果两张表各自漏登记(README 漏 5 个、本文漏 9 个,2026-10-30 实测),同一条事实两处 登记必然漂移 → 现只留一处,本文只讲**怎么选、怎么画、怎么审**。 - 要新增一张精确布局图:先到那张表按主题找最接近的生成器**照抄骨架**(`draw-diagram` skill §二), 落库时**同批把行加进那张表**(不往本文加)。 - 要挑工具(SVG 还是 Mermaid 还是截图):看本文 §一 的选型表与维度对比表——那是**判据**,不是清单, 与逐脚本清单不重复。 ### 2.1 钩子扫不到的图:refgraph 产物与历史手画稿 `generated-fresh` 的 `docs-svg` 条目只把 `tools/arch_diagram/gen_*.py` 拷进临时目录重跑逐字节比对。 **本目录生成器不产的那四张图**(`引用关系图.svg`、`引用关系图_模块.svg`、`级联框总览.svg`、 `级联框几何计算.svg`)**全都不在这条钩子的扫描面里**——改了不会有任何人报警,这就是「42 个节点的旧图 挂在 43 个节点的标题下」能一路活到今天的原因。四张图的产物、出处与挂载逐张列在 **`tools/arch_diagram/README.md`「产物清单」**末尾两组,本文不再重复登记;只留维护口径: - **refgraph 两张**(`tools/refgraph/gen_refgraph.py`,graphviz,命名不在 `gen_*.py` 面内):改了代码引用 就跑 `& 'tools\refgraph\gen_refgraph.bat'` 重生成,**svg 与改动同一笔提交**,别只更新 `.dot`; 口径 → `docs/架构设计/引用关系图说明.md`。 - **级联框两张**:手工 SVG、**无生成器**(`git log --follow` 实测 2026-09-08 `891c9ef0` 入库、2026-09-11 `2429955d` 随配图规范收拢进 `docs/images/`,此后未再改动;本文此前写的绘制日期与 git 史不符,已按 git 改)。 只作**显示几何示意**,不承载菜单树事实——树的结构 / 层级 / 绑页走 `docs/images/菜单树总览.svg`(有生成器);坐标公式变了要重算重画,别在 SVG 上描字。 新增精确布局图一律走 `tools/arch_diagram/gen_*.py`(`docs-svg` 条目自动发现,**不必登记基线**);上面这两组 是这套纪律的**例外面**,再多一张先说清为什么不能用生成器。 --- ## 三、绘制流程 ### 3.1 精确布局图(协议帧 / 架构 / 依赖)——用生成器 1. **挑脚本**:协议帧 → `gen_frame_svg.py`;分层架构 → `gen_arch_svg.py`;就绪屏障 → `gen_barrier_svg.py`。 2. **改数据**:编辑脚本顶部数据区。配色沿用既有调色板: | 语义 | 主色 | 底色 | |---|---|---| | 蓝 | `#2563eb` | `#eff6ff` | | 青 | `#0d9488` | `#f0fdfa` | | 绿 | `#16a34a` | `#f0fdf4` | | 琥珀 | `#d97706` | `#fffbeb` | | 紫 | `#7c3aed` | `#f5f3ff` | | 灰 | `#475569` | `#f1f5f9` | | 玫红 | `#e11d48` | `#fff1f2` | 3. **重跑**(仓库根目录;纯标准库,任意 python3,统一用 `.venv` 亦可): ```powershell & '.venv\Scripts\python.exe' tools/arch_diagram/gen_frame_svg.py ``` 成功输出 `OK <字节> bytes, canvas x -> <路径>`。脚本内置 `ElementTree.fromstring` 自检——**XML 不合法会直接抛错**,不会产出坏图。 4. **目检**:小图浏览器直接打开 `docs/images/*.svg`;要留证或回读细节,走本文 §四 的 **headless 浏览器截图** (渲染命令只在那一节详述)。确认文字不溢出盒外、框 / 线 / 标签对齐、配色正确。 **≥20 边的大图**另跑解析式碰撞审计 → **`draw-diagram` skill** §三b(压半格这种问题眼睛看不出来)。 5. **引用**:在对应 `.md` 里用**相对路径**:根目录下的 md 指向 `docs/images/` 下的图(形如 `![帧格式](images/RemoDispBus帧格式.svg)`);`docs/UI设计/` 等子目录的 md 则写 `../images/` 前缀的等价写法。 6. **提交**:脚本(源)+ 生成的 `.svg`(产物)**一起**提交(产物入库,类比生成物 `ui_menu_tab.c`)。 ### 3.2 SVG 约定(手写 / 新增生成器时遵循) - **纯标准库**:只用 `html` / `os`(+ 需要时 `math`)拼 SVG 字符串;**不引第三方库**(SVG 由浏览器用系统字体渲染,无需 Pillow / 字体文件)。 - **文本转义**:所有文本经 `html.escape(s, quote=True)`(`& < > " '` → 实体),防止破坏 XML。 - **字体**:根 ``(系统字体栈,Win / mac 通用)。 - **文本宽估算**(自适应盒宽时):`text_w(s, fs)`——CJK / 全角 / 圈码 / 箭头 ≈ `1.0em`,其余 ≈ `0.58em`(**宁大勿小**,防溢出)。 - **落盘**:`open(OUT, "w", encoding="utf-8", newline="\n")`(UTF-8 无 BOM + LF,符合仓库编码铁律)。 - **自检**:写盘后 `xml.etree.ElementTree.fromstring(svg)`。 - **产物位置**:`docs/images/`(专门配图目录;引用它的 `.md` 用相对路径指向)。 - **命名**:`docs/images/<主题>.svg`(可与同名 `.md` 对应,如 `images/RemoDispBus帧格式.svg` ↔ `RemoDispBus协议与接收设计说明.md` §1.2)。 ### 3.3 拓扑类图(流程 / 时序 / 状态机)——用 Mermaid 在 Markdown 里直接写 ` ```mermaid ` 代码块(GitHub 与多数渲染器原生渲染,**无需生成图片**): ````markdown ```mermaid sequenceDiagram participant C as 客户端 participant S as 服务端 C->>S: LCDMEM 取帧 S-->>C: 1bpp 位图(3200 B) ``` ```` 常用:`flowchart`(流程 / 框图)、`sequenceDiagram`(时序)、`stateDiagram-v2`(状态机)、`erDiagram`(实体关系)。 > ⚠️ Mermaid 盒子宽度自适应、会自动连线,**只适合"关系"类图**;凡需精确像素 / 比例的布局图(协议帧、分层框)一律走 §3.1 的 SVG 生成器。 --- ## 四、SVG → PNG(可选) 默认交付 **SVG**(矢量、可缩放、可 diff、可过门禁)。需要位图(留证、回读细节、贴进不渲染 SVG 的 查看器)时,用**本机实测可用**的 headless 浏览器渲染: ```powershell # Edge / Chrome 都不在 PATH 上,按全路径调用(本机实测两者都在;换机先核这两个路径在不在, # Chrome 的那条是 C:\Program Files\Google\Chrome\Application\chrome.exe)。 # --screenshot 必须给绝对 Windows 路径:相对路径报 `Failed to write file …(0x3)` 且 PNG 压根不落盘。 # --window-size 要跟 SVG 画布一致:忘了改会截出大片空白或裁掉底部脚注。 & 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe' --headless --disable-gpu ` --hide-scrollbars --window-size=, --virtual-time-budget=10000 ` --screenshot="$env:TEMP\preview.png" "file:///<仓库根绝对路径,正斜杠>/docs/images/RemoDispBus帧格式.svg" ``` > **别照旧写法装 `cairosvg`**:`.venv` 里没装(`ModuleNotFoundError`)、`requirements.txt` 里也没有, > `rsvg-convert` / `inkscape` / `magick` 这台机器上都不存在(2026-10-30 实测)。真要引入是**动 > `requirements.txt` 的决定**(第三方依赖统一进那里;另注意门禁 entry 的裸 `python` 不等于 `.venv` → > AGENTS.md「Python 环境」),不是画图这一步的隐含前置。零工具兜底仍是「浏览器双击打开 `.svg` 用眼看」, > 但半格压框这类问题靠眼看不出来。 > PNG 属**本地派生物、不入库**:忽略规则是 `.gitignore` 里针对目录的三条——`docs/images/*.png`(:132)、 > `simulator/shot*.png`(:106)、`simulator/tests/ref/*.png`(:127),**不是**一条全库 `*.png`。 > 另注意 `simulator/tests/ref/` 下作为像素黄金参考的 `.bin` **是入库的**,别顺手一起忽略掉。 --- ## 五、检查清单(提交前) - [ ] 生成器输出 `OK … bytes`(无异常 = XML 合法)。 - [ ] 目检(小图浏览器打开;要留证走 §四 的 headless 截图):文字不溢出、框 / 线 / 标签对齐、配色符合调色板。 - [ ] 引用它的 `.md` 里图片**相对路径**正确(能显示)。 - [ ] 脚本 + 产物 `.svg` **一并**暂存(产物入库)。 - [ ] `pre-commit run --files <脚本> ` 全过(无乱码 / 行尾空白 / 编码 OK)。