Files
STM32F4-Base/docs/架构设计/图形绘制流程.md
T
wandering1 a38f862fb9 chore(ui-golden): 像素黄金参考 ref/*.bin 入库(把门禁改成可移植)
问题:ui-golden 是逐字节比对(check_content_pages.py 里 data == refdata),
而基准 simulator/tests/ref/ 整目录被 .gitignore 忽略、从未入库。后果不是
"少几个文件",而是这条门禁在任何新克隆 / 新并行工作树里必然报「缺黄金
参考」——只在有老副本的机器上它才是真的回归门禁。本会话已两次实测踩到
(并行工作树里只能现场 --update 造基准,而现场造出来的基准恰好失去意义)。

入库前先证明基线可复现,否则等于把一条天天误报的门禁写进仓库:
- 主树 ref/ 生成于 2026-10-11,其间合入 B6~B9 与 UI 令牌化等多次改动;
  今天用刚重建的 lvgl_sim 重跑 → 11 页 + 开页-关页往返池水位逐字节全过
- 主树与新工作树两份**独立构建**的 lvgl_sim(不同构建目录、不同绝对路径)
  各自生成基准 → 11 个 .bin 的 SHA-256 全部一致
即渲染是 CPU 侧确定性输出,可以当仓库内容。

改动:
- .gitignore:整目录忽略 → 只忽略派生的目检 PNG。另加一条
  !simulator/tests/ref/*.bin 反选——第 115 行的全仓 *.bin 兜底(挡
  sim_netcfg.bin 之类运行产物)会把基线一起挡掉,且反选必须排在它之后
  才生效
- 不引入 LFS:11 x 3200 B = 34.4 KB(160x160 单色打包)。走 LFS 反而新增
  失效面——没拉 LFS 的克隆会拿 pointer 文本去比像素,把"缺基准"换成
  "比不中"。.gitattributes 已有 *.bin binary,check-attr 确认 text unset,
  不会被行尾转换改写
- 基线不会被改写型钩子毁掉:trailing-whitespace / end-of-file-fixer 声明
  types: [text],位图含 NUL 被判二进制 → 实测 Skipped;索引 blob、磁盘、
  主树参照三方哈希 11/11 一致
- 新增 11 个基线;同步 5 份文档与 3 处脚本口径:缺基准的提示从"首次/换机
  请加 --update"改为"检出不完整 → git checkout -- simulator/tests/ref/ 取回,
  不要用 --update 就地造基准"(旧提示正是自我实现型基准的来源)
- 顺带修掉 simulator/tests/README.md 两处与实现不符的描述:基准写成 PNG
  (实为 .bin)、regen_ref_png.py 写成"重建黄金参考"(它只出目检图,基准
  由 check_content_pages.py --update 刷)
- .pre-commit-config.yaml 只改注释(原文明确断言 ref/ "永远不会进 git
  索引",已被本改动推翻);ui-golden 的 files 面覆盖 simulator/tests/,
  基线被改即触发回归,刷参考从此在 git diff 里显形

历史口径按纪律冻结:UI_自动化测试流程 2026-09-10 的"整目录不入库"等 6 处
变更记录行不改写,以新行登记反转。

实测:@build 0 错 0 警(Code=213520,与内存台账一致);ui-golden Passed;
pre-commit run --all-files = 36 Passed / 0 Failed(RC=0)。
2026-10-22 06:17:00 +08:00

145 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 图形绘制流程(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_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/`)
以下生成器共享同一套约定(§3.2),均为**纯标准库**拼 SVG:
| 脚本 | 产物(入库) | 顶部数据区(改这里 → 重跑) |
|---|---|---|
| `gen_arch_svg.py` | `docs/images/项目架构总览.svg` | `LAYERS` / `ROWS` / `FOOT` |
| `gen_barrier_svg.py` | `docs/images/就绪屏障.svg` | `BITS` / `PRODUCERS` / `CONSUMERS` |
| `gen_frame_svg.py` | `docs/images/RemoDispBus帧格式.svg` | `FIELDS` / `TITLE` / `SUB` / `FOOT` |
| `gen_storage_stack_svg.py` | `docs/images/存储栈分层.svg` | `L_*` / `ROWS` / `TITLE` / `SUB` / `FOOT` |
| `gen_partition_svg.py` | `docs/images/物理分区布局.svg` | `FIELDS` / `TITLE` / `SUB` / `FOOT`(MB 计量) |
| `gen_net_pending_svg.py` | `docs/images/Net层阻塞模型.svg` | `CALLER_STEPS` / `LOOP_STEPS` / `PHASES` |
| `gen_cfg_arch_svg.py` | `docs/images/配置文件分层架构.svg` | 配置引擎分层 |
| `gen_net_stack_svg.py` | `docs/images/BSD网络栈分层.svg` | BSD 网络栈分层 |
| `gen_memory_svg.py` | `docs/images/内存布局_*.svg` | RAM / FLASH 布局 |
| `gen_watchdog_svg.py` | `docs/images/看门狗心跳模型.svg` | `TASKS` / `REQ_BITS` / `POLL_STEPS` / `TIMELINE` |
---
## 三、绘制流程
### 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 <W>x<H> -> <路径>`。脚本内置 `ElementTree.fromstring` 自检——**XML 不合法会直接抛错**,不会产出坏图。
4. **目检**:浏览器打开 `docs/images/*.svg`,确认文字不溢出盒外、框 / 线 / 标签对齐、配色正确。
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。
- **字体**:根 `<svg font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">`(系统字体栈,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 的查看器**需要位图时再转 PNG:
- **最简单**:浏览器打开 `.svg` → 截图 / 另存为图片。
- **脚本化**:给 `.venv` 装 `cairosvg` 后转(`scale=2` 提高清晰度):
```powershell
& '.venv\Scripts\python.exe' -m pip install cairosvg
& '.venv\Scripts\python.exe' -c "import cairosvg; cairosvg.svg2png(url='docs/images/RemoDispBus帧格式.svg', write_to='remo.png', scale=2)"
```
> PNG 属**本地派生物、不入库**(与 `simulator/tests/ref/*.png` 目检图一致,`.gitignore` 已含
> `*.png`;注意该目录下作为像素黄金参考的 `.bin` **是入库的**,别顺手一起忽略掉)。
---
## 五、检查清单(提交前)
- [ ] 生成器输出 `OK … bytes`(无异常 = XML 合法)。
- [ ] 浏览器目检:文字不溢出、框 / 线 / 标签对齐、配色符合调色板。
- [ ] 引用它的 `.md` 里图片**相对路径**正确(能显示)。
- [ ] 脚本 + 产物 `.svg` **一并**暂存(产物入库)。
- [ ] `pre-commit run --files <脚本> <svg> <md>` 全过(无乱码 / 行尾空白 / 编码 OK)。
---
## 六、变更记录
| 日期 | 变更 |
|---|---|
| 2026-09-11 | 创建:统一图形绘制流程(选型 / SVG 生成器 / Mermaid / 约定 / 检查清单);新增 `tools/arch_diagram/gen_frame_svg.py`(通用协议帧图)+ `docs/images/RemoDispBus帧格式.svg` |
| 2026-09-11 | 新增专门配图目录 `docs/images/`:收拢 `docs/` 根与 `docs/UI设计/images/` 下 5 张 SVG;同步更新 3 个生成器 OUT 路径、4 处文档图片引用、`AGENTS.md` 与 `.gitignore`(PNG 预览规则);流程沉淀为 `draw-diagram` skill |
| 2026-09-11 | 存量 ASCII 框图清理:`STM32F4-Base存储架构说明.md` 两图(存储栈分层 / 物理分区布局)重绘为 SVG(生成器家族新增 `gen_storage_stack_svg.py` / `gen_partition_svg.py`);`RemoDispBus协议与接收设计说明.md` 删 ASCII 帧图(SVG 帧格式图已在,信息无损失);`测试说明/CH395F_Test_Guide.md` 4 图(2 组件架构 + 2 会话时序)转 Mermaid |
| 2026-10-22 | 澄清 §派生物一句:`simulator/tests/ref/` 下作为像素黄金参考的 `.bin` 已入库,只有派生的 `.png` 目检图仍不入库(原表述把两者混为"参考图不入库",会诱导后来者把整个目录继续忽略掉) |