Skip to content

Commit 438a0ed

Browse files
authored
[0109] 修复子表格与外部表格边框重叠及间隙问题 (#3332)
1 parent aba574f commit 438a0ed

4 files changed

Lines changed: 130 additions & 11 deletions

File tree

TeXmacs/tests/tmu/0109.tmu

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<TMU|<tuple|1.1.0|2026.2.4>>
2+
3+
<style|<tuple|generic|chinese|table-captions-above|number-europe|preview-ref>>
4+
5+
<\body>
6+
<\big-table|<block|<tformat|<table|<row|<cell|>|<cell|>|<cell|>>|<row|<cell|>|<cell|<subtable|<tformat|<cwith|1|-1|1|-1|cell-tborder|1ln>|<cwith|1|-1|1|-1|cell-bborder|1ln>|<cwith|1|-1|1|-1|cell-lborder|1ln>|<cwith|1|-1|1|-1|cell-rborder|1ln>|<table|<row|<cell|>|<cell|>>|<row|<cell|>|<cell|>>>>>>|<cell|>>|<row|<cell|>|<cell|这是一个单元格>|<cell|>>>>>>
7+
\;
8+
</big-table>
9+
</body>
10+
11+
<\initial>
12+
<\collection>
13+
<associate|page-medium|paper>
14+
<associate|page-screen-margin|false>
15+
</collection>
16+
</initial>
17+
18+
<\references>
19+
<\collection>
20+
<associate|auto-1|<tuple|1|1>>
21+
</collection>
22+
</references>
23+
24+
<\auxiliary>
25+
<\collection>
26+
<\associate|table>
27+
<tuple|normal|<\surround|<hidden-binding|<tuple>|1>|>
28+
\;
29+
</surround>|<pageref|auto-1>>
30+
</associate>
31+
</collection>
32+
</auxiliary>

devel/0109.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# [0109] 修复子表格编辑辅助线与外部表格的间隙问题
2+
3+
## 相关文档
4+
- [dddd.md](dddd.md) - 任务文档模板
5+
- [0403.md](0403.md) - 相关任务文档(合并单元格后编辑线条重叠问题)
6+
7+
## 任务相关的代码文件
8+
- `src/Typeset/Table/table.cpp`
9+
- `src/Typeset/Table/cell.cpp`
10+
- `src/Edit/Interface/edit_interface.cpp`
11+
12+
## 如何测试
13+
14+
### 确定性测试(单元测试)
15+
```bash
16+
# 无单元测试
17+
```
18+
19+
### 非确定性测试(文档验证)
20+
测试文档:`TeXmacs/tests/tmu/0109.tmu`
21+
22+
```bash
23+
# 编译并运行 Mogan,打开 TeXmacs/tests/tmu/0109.tmu
24+
# 确保「编辑 -> 首选项 -> 其他 -> 显示表格单元格」已开启
25+
# 将光标放入中间单元格的子表格中
26+
# 观察子表格的编辑辅助细线(env_rects)与外部 3x3 表格的中间单元格边框是否完全重合
27+
# 修复前:子表格边框与外部单元格边框之间存在微小间隙
28+
# 修复后:两者应完全重合,无间隙
29+
```
30+
31+
## 如何提交
32+
33+
提交前执行以下最少步骤:
34+
35+
```bash
36+
# 运行代码格式化
37+
bin/format
38+
39+
# 确认修改仅涉及指定文件
40+
git diff --stat
41+
```
42+
43+
## What
44+
45+
修复在编辑状态下,嵌套于单元格中的子表格辅助边框线与外部单元格边框线未完全重合、存在间隙的问题。
46+
47+
1.`cell.cpp` 处理 `SUBTABLE` 时,当前代码虽然将子表格所在单元格的 `lsep/rsep/bsep/tsep` 显式设为 0,但传入 `typeset_subtable``var` 仍可能携带父单元格的 `CELL_LSEP`/`CELL_RSEP`/`CELL_BSEP`/`CELL_TSEP` 等格式变量。
48+
2. 子表格通过 `inherited_format(var)` 继承这些变量,导致子表格内部单元格的默认 `lsep`/`rsep` 等使用 `env->fn->spc->def`(非零默认值),而非与父单元格一致的 0 值。
49+
3. 这使得子表格内部单元格的排版边界与外部单元格的边界产生偏移,在 `compute_env_rects` 绘制的编辑辅助线(env_rects)上表现为子表格边框与外部单元格边框之间的可见间隙。
50+
4. 修复方式:在 `cell.cpp``typeset` 函数中,构造子表格前,从传入的 `var` 中显式移除 `CELL_LSEP``CELL_RSEP``CELL_BSEP``CELL_TSEP` 键,确保子表格内部单元格不继承父单元格的 sep 值,从而使其边框与外部单元格边框完全重合。
51+
52+
## Why
53+
54+
在无框表格中,用户期望子表格能够完全贴合父单元格的边界。当前实现虽然将子表格所在单元格本身的 sep 设为 0,但通过 `inherited_format` 机制,子表格内部单元格仍继承了父单元格的 sep 格式变量(或环境默认值)。这些额外的 padding 导致子表格内容的排版范围与父单元格边界不一致,在编辑辅助线渲染时产生可见间隙,影响视觉体验。
55+
56+
## How
57+
58+
`src/Typeset/Table/cell.cpp``cell_rep::typeset` 函数中,处理 `SUBTABLE` 的分支内,于调用 `typeset_subtable` 之前,从 `var` 中移除以下键:
59+
60+
- `CELL_LSEP`
61+
- `CELL_RSEP`
62+
- `CELL_BSEP`
63+
- `CELL_TSEP`
64+
65+
这样 `inherited_format(var)` 将不会把这些 sep 值传递给子表格,子表格内部单元格将使用与父单元格一致的 sep=0,确保两者边框重合。

src/Typeset/Table/cell.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ cell_rep::typeset (tree fm, tree t, path iq) {
3333
cell_local_begin (fm);
3434
if (is_func (t, SUBTABLE, 1)) {
3535
lsep= rsep= bsep= tsep= 0;
36-
T = table (env, 2);
36+
var->reset (CELL_LSEP);
37+
var->reset (CELL_RSEP);
38+
var->reset (CELL_BSEP);
39+
var->reset (CELL_TSEP);
40+
T= table (env, 2);
3741
T->typeset_subtable (t[0], descend (iq, 0), var);
3842
}
3943
else if (is_func (t, DOCUMENT, 1) && is_func (t[0], SUBTABLE, 1)) {
4044
lsep= rsep= bsep= tsep= 0;
41-
T = table (env, 2);
45+
var->reset (CELL_LSEP);
46+
var->reset (CELL_RSEP);
47+
var->reset (CELL_BSEP);
48+
var->reset (CELL_TSEP);
49+
T= table (env, 2);
4250
T->typeset_subtable (t[0][0], descend (descend (iq, 0), 0), var);
4351
}
4452
else {
@@ -386,7 +394,7 @@ cell_rep::position_horizontally (SI offset, SI mw, SI lw, SI rw) {
386394
else xoff= lw;
387395
if (N (halign) > 1) xoff-= b->get_leaf_offset (halign (1, N (halign)));
388396
}
389-
else xoff= -T->x1 + lborder;
397+
else xoff= -T->x1;
390398
}
391399

392400
void
@@ -404,7 +412,7 @@ cell_rep::position_vertically (SI offset, SI mh, SI bh, SI th) {
404412
else if (align_c == 'T') yoff= mh - th;
405413
else yoff= bh;
406414
}
407-
else yoff= -T->y1 + bborder;
415+
else yoff= -T->y1;
408416
}
409417

410418
/******************************************************************************
@@ -452,7 +460,13 @@ cell_rep::finish () {
452460
b= T->b;
453461
}
454462

455-
b= cell_box (ip, b, xoff, yoff, 0, 0, x2 - x1, y2 - y1, lborder, rborder,
456-
bborder, tborder, dborder, aborder, env->pen->get_brush (),
457-
brush (bg, env->alpha));
463+
if (!is_nil (T)) {
464+
b= cell_box (ip, b, xoff, yoff, 0, 0, x2 - x1, y2 - y1, 0, 0, 0, 0, 0, 0,
465+
env->pen->get_brush (), brush (bg, env->alpha));
466+
}
467+
else {
468+
b= cell_box (ip, b, xoff, yoff, 0, 0, x2 - x1, y2 - y1, lborder, rborder,
469+
bborder, tborder, dborder, aborder, env->pen->get_brush (),
470+
brush (bg, env->alpha));
471+
}
458472
}

src/Typeset/Table/table.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,18 @@ table_rep::merge_borders () {
466466
kk= ii * hh + jj;
467467
bb= max (verb[kk], bb);
468468
}
469-
C->lborder= lb;
470-
C->rborder= rb;
471-
C->bborder= bb;
472-
C->tborder= tb;
469+
if (!is_nil (C->T)) {
470+
C->lborder= 0;
471+
C->rborder= 0;
472+
C->bborder= 0;
473+
C->tborder= 0;
474+
}
475+
else {
476+
C->lborder= lb;
477+
C->rborder= rb;
478+
C->bborder= bb;
479+
C->tborder= tb;
480+
}
473481
}
474482
}
475483
}

0 commit comments

Comments
 (0)