ebox/DESIGN.zh.md

87 lines
6.5 KiB
Markdown
Raw Permalink 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.

# Ebox 设计
Ebox 是底层空间渲染引擎。它负责把声明式节点树转换为经过测量的布局 fragment 与通用 TP surface plan。它有意小于应用框架。
## 设计原则
- 一棵 source tree、一套样式归一化、一条布局流水线、一个 buffer owner。
- 公共节点是数据;只有显式入口负责渲染与变更。
- 稳定 identity 来自节点 identity 和显式 key不来自可见文本或 selector 字符串。
- 布局变化先测量再发布;候选发布失败时保留上一个 buffer 状态。
- native 模块只是可选加速器,必须有完全等价的 Elisp fallback。
- 新抽象必须消除重复,或让已有的公共工作流更简单。
- 公共 property schema、ECSS metadata 与 used engine projection 都从同一 property definition record 派生。
- 跨包 framework integration 只发布 additive versioned providerconsumer selection 与 fallback policy 不属于 Ebox。
## 流水线
```text
节点树
-> 归一化样式
-> 经过测量的 formatting context
-> 布局 fragment 与 snapshot
-> render context
-> 纯 TP surface plan
```
各层 owner 是:`ebox-child-range.el` 负责不可变 child sequence 与 key index`ebox-tree.el` 负责 Ebox identity 与遍历,`ebox-style.el` 负责样式语义,`ebox-measure.el` 负责 display 敏感测量,`ebox-layout.el`、`ebox-flex.el`、`ebox-grid.el` 负责几何,`ebox-fragment.el` 负责 fragment 事实,`ebox-render-context.el` 负责 candidate/materialization 输入 port`ebox-patch-plan.el` 负责纯 operation-antichain artifact`ebox-surface.el` 负责纯 TP plan 投影与 retained 发布,`ebox-incremental.el` 负责 dirty 分类与 live fact 适配。`ebox-layout.el` 不再 load 或调用 surface/TP 层;门面把 surface operation 接入已校验的 render-context port。patch planner 不读取 buffer 或 surfaceincremental adapter 只传入不可变 parent fact 与 tentative operation。`ebox-buffer-backend.el` 只构造和整形带文本属性的 render string所有公共 live buffer 发布路径都经过 TP surface 边界。
## 公共边界
使用 `docs/user/ebox-api-reference.zh.md` 中的函数与 property门面清单是 `ebox-public-api`。应用和同级包不得调用 `ebox--*` 私有名称。更高层的 Component、响应式、behavior、data 和 control 概念属于 ETAF。
ECSS 与 TP 是必需的包依赖即使作者没有写选择器或样式表也需要。EKP 是独立的可选
排版依赖:选择 `:wrap-mode kp` 时需要它的公开段落排版 API。EKP 不可用或不兼容时
会报错,不会擅自替换换行算法。它的加速器与 Ebox Rust reflow 模块相互独立。
`ebox-display-buffer` 先渲染,再把窗口放置交给原生 `display-buffer`。它接受调用方的
display action、返回 buffer不选择独占窗口布局也不选中结果窗口。一个 buffer
拥有一套挂载布局与视口;需要独立尺寸的视图应使用不同 buffer不在同一段文本上
维护互相竞争的布局。
## 布局范围
Ebox 支持显式 `px`、`%`、`vw`、`vh`、`ch`、`lh` 尺寸、padding、margin、border、颜色、overflow、换行、row/column/flex formatting以及固定、分数、隐式、gap、放置、span 和对齐等 Grid 能力。公共 typography 子集是 `:font-family`、以 CSS reference pixel 表示的 `:font-size`、`:font-weight` 和 `:font-style``:font-slant` 只是 `:font-style` 的精确 parse-time alias。任意 Emacs face 和文本属性 plist 属于最终 adapter不是 Ebox 作者输入;四种显式原生能力 `:help-echo`、`:pointer`、`:hover-style`、`:keymap` 单独受支持。CSS 兼容性有意是部分实现绝对定位、z-index、阴影、border radius、完整浏览器 typography 和浏览器级 bidi 不属于本包。
文本簇模型覆盖常见组合音标、变体选择符、Emoji 修饰符、ZWJ 序列和区域指示符配对。
它的范围小于完整 Unicode 字素分段;字符数量或这个有限的分段模型,都不能保证任意
字体塑造结果相同。
可选交互导航在当前渲染的 keymap owner 之间移动 point读取已提交 surface尊重
narrowing 与不可见性不安装按键绑定、焦点注册表或应用状态。action 与状态仍属于
调用方。
横向 `:overflow hidden` 在内容组合后、自身 padding 和 border 添加前执行。它选取
测量后能容纳的完整受支持文本簇前缀,再用空白补齐剩余像素。固定 display space 可以
缩短,字形与图像不做局部位图裁剪;裁掉的子节点属性不会残留在中性填充上。
算法按 GPL-3.0-or-later 复用了
[s-pixel](https://github.com/Kinneyzhang/s-pixel/tree/a2a0d6ae6b3bd71c1a70084d0ea37f56463e5fe0)
的前缀加空白补齐思路,适配 Ebox 的文本簇与属性模型,不增加 `s``s-pixel` 依赖,
也不引入层叠或重叠组合。
## 尺寸组合
`ebox-size.el` 负责长度验证、依赖识别、浮点像素换算,并提供累计量化的纯函数,
供布局在选定的显示边界调用。上下文显式传入视口两轴、
该属性的百分比参照、`0` 字形前进宽度和行高;模块不读取窗口或节点,不求值任意
Lisp不选择属性默认值也不发布 buffer。Normal、Flex、Grid、间距和边框几何
由此复用同一套单位运算。
作者格式为 `(单位 数值)`,可组合函数是 `calc`、`min`、`max`、`clamp`。
property schema 负责允许的单位、关键词和值域。[统一单位约束表](docs/user/ebox-user-guide.zh.md#size-unit-constraints)
是作者契约inline 几何、block 几何和边框绘制采用不同单位集合。验证递归遍历
所有函数分支和轨道参数Flex basis 使用所在父布局主轴。无效单位组合在构造阶段
就报错,不延后到布局或显示。
布局负责提供包含块及字体测量,并解析固有/自动尺寸。`fit-content` 只接受裸关键词。
旧的裸长度、单元素像素列表、视口
关键词和 `contain` 不保留兼容执行路径。
参照尺寸缺失时延后解析,不当作零;中间运算保留小数,到格式化/显示边界才量化。
buffer 后端按完整行生成 block 几何,与收窄后的纵向单位契约一致。空 Box 的自动
内容高度为零需要占位时由显式高度、padding 或 border 提供对应尺寸。
## 验证规则
每个行为修改都要补充聚焦的 ERT 测试,并运行新的 `make check`。修改 native 源码还要运行 `make native-rust-tests`;修改文档或 active 文件集合还要运行 `make docs-contract-tests`