docs(terminal): update roadmap after renderer and addon work
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
> 定位提醒:本项目目标不是复刻 xterm.js 这个通用 JS 终端库,而是按 [TERMINAL_HANDOFF.md](TERMINAL_HANDOFF.md) 的方向,用 `Axum + portable-pty`(后端)+ `Leptos + Rust/WASM`(前端)沉淀一套**高性能、可复用的 Rust 终端组件**。因此追平的重点是「让真实终端会话好用且性能好」,而非铺平 xterm.js 的全部 API 面。
|
||||
>
|
||||
> **性能目标**:当前 DOM 渲染在 80×24–160×40 的常规终端下足够流畅,但大终端(≥200×100)或高刷新率连续输出场景会出现 DOM 节点过多、重排重绘开销大的问题。因此**渲染器最终要迁到 Canvas / WebGL**,这是明确的长期目标,会在 P3 之后按优先级推进。
|
||||
> **性能目标**:终端默认渲染器已切到 WebGL glyph atlas / per-cell quad,保留 Canvas 2D 与 DOM renderer 作为回退。Canvas 2D 解决了大部分 DOM 节点膨胀、长输出重排和高频输出卡顿问题;WebGL 路径现在按字形 atlas 缓存并批量绘制单元格 quad。
|
||||
|
||||
---
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
按用途粗估:
|
||||
|
||||
- **「跑通真实终端会话」核心用途**:约 **75–80%**
|
||||
- **xterm.js 完整 API / 特性面**:约 **20–25%**
|
||||
- **「跑通真实终端会话」核心用途**:约 **85%**
|
||||
- **xterm.js 完整 API / 特性面**:约 **40%**
|
||||
|
||||
差距集中在**输入完整性**、**API/生态**、**可配置性**,而非「能不能用」。
|
||||
差距集中在 **API/插件生态、accessibility、搜索/链接、Unicode 深度精度、运行时可配置性、工程化性能基准**,而非「能不能用」。
|
||||
|
||||
### 已实现(有代码 + 单元测试)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
| 文本选区 + 复制(自建模型,Ctrl-Shift-C / 选区存在时 Ctrl+C,跨滚动) | `component.rs` 鼠标处理 / `core.rs::selection_text` |
|
||||
| 鼠标上报(vim/htop/tmux 鼠标,SGR/Default/UTF-8 编码,滚轮) | `component.rs` 鼠标处理 / `encode_mouse_report` |
|
||||
| 中文 / IME 输入(拼音/日文/韩文,隐藏 textarea + composition 事件) | `component.rs::handle_input` / `handle_composition_*` |
|
||||
| WebGL glyph atlas 默认渲染器(per-cell quad、DPR glyph atlas、背景/underline/cursor backdrop、Canvas/DOM 回退) | `component.rs::Renderer` / `render_webgl` / `GlyphAtlas` / `render_canvas` / `canvas_render_plan` |
|
||||
|
||||
---
|
||||
|
||||
@@ -135,22 +136,105 @@
|
||||
|
||||
---
|
||||
|
||||
### P4 — Canvas / WebGL 渲染器(性能目标)
|
||||
### P4 — Canvas / WebGL 渲染器(性能目标)✅ 已完成
|
||||
|
||||
**现状**:DOM 渲染。常规 80×24–160×40 终端流畅,但大终端(≥200×100)或高刷新率连续输出时,DOM 节点多、重排重绘开销大。
|
||||
**现状**:WebGL glyph atlas / per-cell quad 已作为默认渲染器;Canvas 2D 与 DOM renderer 保留为回退路径。长输出、输入后 live/history 稳定性、IME textarea buffer 坐标、DPR backing store、虚拟滚动 sizer、selection overlay、cursor overlay 均已验证。
|
||||
|
||||
**已实现**:
|
||||
1. **WebGL glyph atlas 默认渲染器** ✅
|
||||
- `Renderer::WebGl` 默认,`Renderer::Canvas` / `Renderer::Dom` 作为回退。
|
||||
- WebGL2 初始化 shader/program/vertex buffer/atlas texture/fallback texture。
|
||||
- `GlyphAtlas` 按 grapheme + bold/italic + cell width 缓存字形;ASCII、CJK wide 字符、组合字符按 `unicode-segmentation` / `unicode-width` 拆成 cell glyph。
|
||||
- 文本通过 per-cell quad 批量绘制,颜色作为 vertex attribute;小字号不再走整屏纹理二次采样。
|
||||
- 背景、underline、cursor 背景由 Canvas backdrop 绘制后作为底层 texture 合成;cursor 前景文字仍进 atlas。
|
||||
- atlas 溢出或遇到不可拆分复杂段时自动回退整屏 Canvas texture,避免真实终端内容白屏。
|
||||
- WebGL2 不可用时自动落回 Canvas 2D。
|
||||
2. **Canvas 2D 渲染器** ✅
|
||||
- 保留现有 `TerminalCore` 数据模型,渲染层切换为 Canvas。
|
||||
- 一屏/一窗口 `fillText` / `fillRect` 绘制,避免每个 segment 都生成 DOM 节点。
|
||||
- DPR backing store 与 CSS 尺寸分离,避免高 DPI 模糊。
|
||||
- `CanvasRenderPlan` 统一计算 backing store、CSS size、canvas top、content offset。
|
||||
- `CanvasDomState` 缓存 DOM 尺寸状态,避免每帧无意义重设 backing store。
|
||||
- 保留 `terminal-virtual-sizer` 维持完整 scroll geometry,长 `cat` 后 live 模式稳定贴底。
|
||||
- selection overlay 保持 DOM 绝对定位,canvas 只负责文本/背景/光标。
|
||||
- IME textarea 改用 buffer 坐标定位,长 scrollback 后输入不会触发 live/history 抖动。
|
||||
3. **测试** ✅
|
||||
- `canvas_render_plan`、`canvas_fill_style`、`terminal_font`、`canvas_viewport_top_px`、`ime_cursor_cell`、`webgl_quad_vertices`、`webgl_shader_sources`、`GlyphAtlas`、`split_segment_glyphs`、`push_quad` 均有单测。
|
||||
- `cargo test -p app --lib terminal::` 当前 38 个 terminal 测试通过。
|
||||
|
||||
**后续深化(进入新一轮 xterm.js 对标计划)**:
|
||||
1. WebGL context loss/recovery 与 atlas 重建。
|
||||
2. 渲染性能基准:固定脚本覆盖 10k/50k 行输出、200×80、240×100、持续输出 FPS / frame time。
|
||||
3. 浏览器截图 + canvas/WebGL pixel smoke test 固化到工程化脚本。
|
||||
4. emoji / ZWJ / variation selector / ligature 的 advanced shaping 策略。
|
||||
|
||||
---
|
||||
|
||||
### P5 — xterm.js API / 配置面(新一轮)✅ 已完成
|
||||
|
||||
**目标**:把当前 `TerminalPanel` 从页面内组件推进成可复用终端组件。
|
||||
|
||||
**已实现**:
|
||||
1. `TerminalOptions` ✅
|
||||
- cols/rows、scrollback、renderer、font family/size/line-height、theme、cursor style/blink、title/subtitle、show_header。
|
||||
- 支持 runtime options signal 更新;字体、行高、theme 同步到 DOM / Canvas / WebGL glyph atlas / 虚拟滚动计算。
|
||||
- `TerminalCore::new_with_scrollback` 让 scrollback 容量进入 parser 层,而不只是 UI 参数。
|
||||
2. `TerminalHandle` ✅
|
||||
- `write`、`paste_text`、`clear`、`focus`、`resize`、`scroll_to_bottom`、`copy_selection`。
|
||||
3. 事件回调 ✅
|
||||
- `on_data`、`on_resize`、`on_selection_change`、`on_title_change`、`on_render`。
|
||||
4. 测试 ✅
|
||||
- 新增 options 解析 / CSS 变量 / 行高参数化 / cursor shape / cursor glyph color 相关单测。
|
||||
- `cargo test -p app --lib terminal::` 当前 41 个 terminal 测试通过。
|
||||
5. 第一轮模块拆分 ✅
|
||||
- `keyboard.rs`:paste normalization、key mapping、printable key 判断。
|
||||
- `mouse.rs`:wheel rows、mouse report 编码、visible grid mapping。
|
||||
- `selection.rs`:selection model、selection rect 计算。
|
||||
- `ime.rs`:IME cursor buffer 坐标和 hidden textarea helpers。
|
||||
|
||||
**后续进入 P6**:
|
||||
1. `TerminalHandle` 增强:`fit()`、serialize/search/link addon 接口。
|
||||
2. 继续把 WebGL / Canvas renderer 从 `component.rs` 拆成专门模块。
|
||||
|
||||
### P6 — xterm.js addon parity(搜索 / 链接 / 序列化 / fit)
|
||||
|
||||
**当前进度**:
|
||||
1. **Fit addon 等价能力**
|
||||
- ✅ `TerminalHandle::fit()`,根据容器内容区重新测量 rows/cols,更新 core viewport 并同步 PTY resize。
|
||||
2. **Search**
|
||||
- ✅ `TerminalHandle::search_next/search_previous/clear_search`。
|
||||
- ✅ literal search 跨 `history + screen`,支持 wrap,搜索结果通过 DOM overlay 高亮,WebGL/Canvas/DOM renderer 共用。
|
||||
3. **Serialize**
|
||||
- ✅ `TerminalHandle::serialize_text()` 与 `TerminalCore::buffer_text()`,导出当前 retained buffer 文本。
|
||||
- ✅ `TerminalHandle::serialize_ansi()` 与 `TerminalCore::buffer_ansi()`,按当前 row/style 模型导出 ANSI-styled snapshot。
|
||||
4. **Web links / OSC 8**
|
||||
- ✅ URL 自动识别、点击打开,WebGL/Canvas/DOM renderer 共用链接 hitbox overlay。
|
||||
- ✅ OSC 8 hyperlink 解析:支持 BEL / ST 终止,使用 cell-grid sidecar 记录链接,覆盖写入、常见 CSI 光标移动、清行/清屏、滚屏进 history 后仍能正确映射到链接 hitbox overlay。
|
||||
- 后续可继续扩展非常规控制序列覆盖面,但 P6 addon parity 的核心能力已完成。
|
||||
|
||||
### P7 — Accessibility / 可访问性
|
||||
|
||||
**计划实现**:
|
||||
1. **Canvas 2D 渲染器(先做)**
|
||||
- 一屏单元格一次 `fillText` / `fillRect` 绘制,减少 DOM 节点。
|
||||
- 保留现有 `TerminalCore` 数据模型,渲染层换成 Canvas。
|
||||
- 文本选区用 Canvas 半透明矩形;光标用 Canvas 反色或额外 DOM overlay。
|
||||
2. **WebGL 渲染器(后做)**
|
||||
- 把字符集预渲染到 texture atlas,用 shader 批量绘制。
|
||||
- 适合超大终端 + 高刷新率场景,但实现复杂度高。
|
||||
3. **可切换**
|
||||
- 默认 DOM,提供 prop/api 切到 Canvas/WebGL。
|
||||
1. screen reader buffer / aria-live 策略。
|
||||
2. keyboard-only selection / copy。
|
||||
3. high contrast / minimum contrast ratio。
|
||||
4. reduced motion 与焦点可见性。
|
||||
|
||||
**风险**:高。需要重新实现渲染层、文本测量、选区高亮、滚动逻辑,同时保证和现有 `TerminalCore` 数据模型兼容。
|
||||
### P8 — Unicode / 字形精度
|
||||
|
||||
**计划实现**:
|
||||
1. emoji / ZWJ / variation selector 的 grapheme cluster 宽度策略。
|
||||
2. CJK ambiguous width 配置。
|
||||
3. ligature 可选支持。
|
||||
4. fallback font metrics 校准。
|
||||
|
||||
### P9 — WebGL Renderer 工程化深化
|
||||
|
||||
**计划实现**:
|
||||
1. WebGL context loss/recovery 与 atlas 重建。
|
||||
2. 渲染性能 benchmark 和自动截图 / pixel smoke test。
|
||||
3. Canvas 2D / WebGL runtime switch。
|
||||
4. 与 Canvas 2D 做 benchmark 对比,按 viewport size / output rate 自动选择 renderer。
|
||||
|
||||
---
|
||||
|
||||
@@ -165,7 +249,17 @@ P2 鼠标上报
|
||||
↓
|
||||
P3 中文 IME(放在功能键之后,避免输入逻辑冲突)
|
||||
↓
|
||||
P4 Canvas/WebGL 渲染器(满足大终端 + 高刷新率性能目标)
|
||||
P4 Canvas / WebGL 渲染器(满足大终端 + 高刷新率性能目标)
|
||||
↓
|
||||
P5 API / 配置面
|
||||
↓
|
||||
P6 addon parity(fit/search/serialize/web-links)
|
||||
↓
|
||||
P7 accessibility
|
||||
↓
|
||||
P8 Unicode / 字形精度
|
||||
↓
|
||||
P9 WebGL renderer 工程化深化
|
||||
```
|
||||
|
||||
每一项都应延续现有做法:**纯逻辑抽成可单测的函数**(如 `map_key_to_terminal_input`、`wheel_delta_to_rows`、`virtual_window`),用 `cargo test -p app --lib terminal::` 锁定,浏览器只做交互验证。
|
||||
|
||||
Reference in New Issue
Block a user