Files
STM32F4-Base/docs/架构设计/图形绘制流程.md
T
wandering1 b49e226815 docs(配图): 菜单树总览改由生成器画,登记钩子扫不到的图
- 新增 tools/arch_diagram/gen_menu_tree_svg.py → docs/images/菜单树总览
  .svg:43 节点 = 9 菜单 + 34 叶,30 已绑页 / 4 未绑 / 16 叶带密码门,
  最深 4 级;读数由脚本现算,不在文档里另抄一份
- 生成器内嵌 NODE_SRC(= ui_menu_tree.txt 的 43 行节点):在仓库里跑会
  与真值逐行互验、不一致 exit 1;generated-fresh 在临时目录重跑读不到
  真值 → 用内嵌表,输出逐字节一致(实测临时目录产物同 sha256)
- 产品需求 §8.2 原先挂的是级联框显示几何图(画的是示例级联,从来不含
  整棵树的节点),换成这张树图,并删掉「该图仍是 42 节点时代所画」的
  补丁注
- 图形绘制流程新增 §2.1:登记 generated-fresh 扫不到的四张图 —— 两张
  tools/refgraph 产物(引用关系图 / _模块,不在 gen_*.py 命名面里)+
  两张手画稿(级联框总览、级联框几何计算)。钩子只扫
  tools/arch_diagram/gen_*.py,这些图改了不会有人报警;再多一张先说清
  为什么不能用生成器
- arch_diagram README 脚本一览加行
2026-10-30 00:25:03 +08:00

11 KiB
Raw Blame History

图形绘制流程(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
gen_adc_frontend_svg.py docs/images/ADC前端电路.svg SUB1 / NOTE_* 等文案常量 + 面板坐标(电路拓扑固定,网表变了才重画)
gen_adc_code_scale_svg.py docs/images/ADC码值刻度.svg PANELS 列表(码范围 / LSB / 实测码标记位置)+ FOOT(换芯片才重画)
gen_data_trust_ladder_svg.py docs/images/数据可信台阶.svg STEPS 五级台阶(状态 / 问题 / 依据)+ BAND_LABEL_1 / GATE_LABEL / FOOTNOTE(台阶状态变了才重画)
gen_data_trust_dc_ac_svg.py docs/images/ADC直流标定与交流验证.svg BOXES_A / BOXES_B 两条泳道 + CHIPS 六件事 + NOTES 红线与"证不到"清单
gen_wave_record_flow_svg.py docs/images/故障录波数据流.svg CHAIN 主链四段 + EDGE 跨边界标签 + TRAPS 三条陷阱 + FORBID 四条红线(所有权、段形态或红线变了才重画)
gen_menu_tree_svg.py docs/images/菜单树总览.svg 内嵌 NODE_SRC(= ui_menu_tree.txt 的 43 行节点)+ 版面常量;仓库里跑会与真值逐行互验,不一致 exit 1(临时目录里读不到真值 → 用内嵌表,输出逐字节一致)

2.1 钩子扫不到的图:refgraph 产物与历史手画稿

generated-fresh 的 docs-svg 条目只把 tools/arch_diagram/gen_*.py 拷进临时目录重跑逐字节比对。 上表没列到的 docs/images/*.svg 就是下面这几张,它们全都不在这条钩子的扫描面里——改了不会有任何 人报警,这就是「42 个节点的旧图挂在 43 个节点的标题下」能一路活到今天的原因。

图 谁画的 用在哪 维护口径
docs/images/引用关系图.svg、docs/images/引用关系图_模块.svg tools/refgraph/gen_refgraph.py(graphviz,不在 gen_*.py 命名面里) docs/架构设计/引用关系图说明.md 的产品 改了代码引用就跑 tools\refgraph\gen_refgraph.bat 重生成,svg 与改动同一笔提交,别只更新 .dot;口径 → docs/架构设计/引用关系图说明.md
docs/images/级联框总览.svg 2026-10-26 手画 docs/UI设计/菜单页面设计.md §4.1(级联框显示几何:根框 + 整定子框) 只作显示几何示意,不承载菜单树事实;树的结构 / 层级 / 绑页 → docs/images/菜单树总览.svg(有生成器)
docs/images/级联框几何计算.svg 同上 docs/UI设计/菜单页面设计.md §5.3(逐框坐标推导) 同上;坐标公式变了要重算重画,别在 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 亦可):

    & '.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 与多数渲染器原生渲染,无需生成图片):

```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 提高清晰度):
    & '.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)。