Skip to content

Commit a5c2e7d

Browse files
da-liiiclaude
andauthored
[204_31] 书籍模式的页面渲染优化 (#3287)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 38cca01 commit a5c2e7d

4 files changed

Lines changed: 79 additions & 19 deletions

File tree

TeXmacs/progs/generic/document-edit.scm

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@
320320

321321
(tm-define (get-init-page-rendering)
322322
(cond ((== (get-init "page-border") "attached") "book")
323+
((and (== (get-init "page-packet") "2")
324+
(== (get-init "page-medium") "paper")
325+
(== (get-init "page-border") "none")) "book")
323326
((!= (get-init "page-packet") "1") "panorama")
324327
((and (== (get-init "page-medium") "paper")
325328
(nnot (tree-innermost 'slideshow))) "slideshow")
@@ -343,11 +346,11 @@
343346
(save-zoom (get-init-page-rendering))
344347
(cond ((== s "book")
345348
(init-env "page-medium" "paper")
346-
(init-env "page-border" "attached")
349+
(init-env "page-border" "none")
347350
(init-env "page-packet" "2")
348-
(init-env "page-offset" "1")
351+
(init-env "page-offset" "0")
349352
(notify-page-change)
350-
(delayed (:idle 25) (restore-zoom s)))
353+
(delayed (:idle 25) (fit-to-screen-width)))
351354
((== s "panorama")
352355
(init-env "page-medium" "paper")
353356
(init-env "page-packet" (number->string (panorama-packets)))

devel/204_31.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# 204_31: 优化书籍模式页面渲染
2+
3+
## 如何测试
4+
5+
1. 新建一个空文档
6+
2. 点击 **文档 -> 页面 -> 页面渲染 -> Book**
7+
3. 观察页面显示:
8+
- 应该显示两页并排(即使只有一页内容,另一页为空白)
9+
- 第一行就应该显示两页,而不是第一行只有一页
10+
- 多页时,同一列的上下页之间应有等距的垂直间隙
11+
4. 添加一些内容产生多页,确认多页时的布局仍然是每行两页,且垂直间隙一致
12+
5. 切换到 Book 模式后,页面会自动 Fit Width(适合宽度)
13+
6. 切换到其他模式(如 Paper、Panorama),确认模式切换正常,菜单 check-mark 显示正确
14+
15+
## 2026/05/08
16+
17+
### What
18+
19+
点击 **文档 -> 页面 -> 页面渲染 -> Book(书籍)** 后,页面渲染存在以下问题:
20+
21+
1. **第一行只有 1 页**:Book 模式设置 `page-offset``"1"`,导致第一页偏移到右侧,第一行只显示 1 页。
22+
2. **空文档只显示 1 页**`pager.cpp``nx = min(page_packet, nr_pages)` 会限制列数为实际页数,空文档(仅 1 页)无法显示两页并排。
23+
3. **行间缺少垂直间隙**`page-border``"none"` 时,页面之间只有水平间隙,同一列的上下页之间没有等距的垂直间隙。
24+
25+
### Why
26+
27+
Book 模式的设计目标是模拟真实书籍的打开状态:两页并排显示,无多余装饰,各页之间有适当留白。当前实现偏离了这一目标:
28+
29+
- `page-offset = "1"` 导致布局不对称,破坏了书籍打开后的自然视觉。
30+
- `nx` 受实际页数限制,空文档无法预览两页并排效果。
31+
- 缺少垂直间隙使多页时的纵向排版过于拥挤,阅读体验差。
32+
33+
### How
34+
35+
#### `src/Typeset/Page/pager.cpp`
36+
37+
- 固定 Book 模式列数:当 `page-packet == 2` 时,`nx = max(1, env->page_packet)`,确保即使只有 1 页也按 2 列排版。
38+
- 添加垂直间隙:当 `page-border == "none"` 时,设置 `vgap = 4 * pixel`,并在 `yy[j]` 的行位置计算中统一减去 `vgap`,保证所有相邻行之间的垂直间隙一致(相对之前增大到两倍)。
39+
- 清理条件编译:移除与 QTTEXMACS 无关的 `#ifdef` 分支,只保留 QTTEXMACS 代码。
40+
- 增大横向间隔:当 `page-border == "none"` 时,左右页之间的水平间隔从 `pixel / 2` 增大到 `pixel`(两倍)。
41+
42+
#### `TeXmacs/progs/generic/document-edit.scm`
43+
44+
- 将 Book 模式的初始化参数改为:
45+
- `page-offset`: `"1"``"0"`
46+
- `page-border`: `"attached"``"none"`
47+
- 扩展 `get-init-page-rendering` 的 Book 模式识别条件:当 `page-packet == "2"``page-medium == "paper"``page-border == "none"` 时,也识别为 Book 模式,确保菜单 check-mark 和模式切换逻辑正确。
48+
- 切换 Book 模式后默认适合宽度:将 Book 模式切换后的缩放行为从 `(restore-zoom s)` 改为 `(fit-to-screen-width)`,使用户进入 Book 模式后自动以适合宽度的比例查看页面。

src/Typeset/Page/make_pages.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ pager_rep::pages_make () {
209209
env->write (PAGE_THE_TOTAL, as_string (n));
210210
for (i= 0; i < n; i++)
211211
pages << pages_make_page (sk[i]);
212+
if (env->page_packet == 2 && (N (pages) & 1) == 1)
213+
pages << pages_make_page (pagelet (space (0)));
212214
}
213215

214216
void

src/Typeset/Page/pager.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -301,26 +301,32 @@ pager_rep::make_pages () {
301301

302302
int nr_pages= N (pages);
303303
int nx = max (1, min (env->page_packet, nr_pages));
304-
int d = env->page_offset % nx;
305-
int ny = ((nr_pages + nx - 1 + d) / nx);
306-
307-
SI pixel= env->pixel;
308-
array<box> pg = pages;
309-
if (env->get_string (PAGE_MEDIUM) == "paper" &&
310-
env->get_string (PAGE_BORDER) != "none")
304+
if (env->page_packet == 2) nx= max (1, env->page_packet);
305+
int d = env->page_offset % nx;
306+
int ny= ((nr_pages + nx - 1 + d) / nx);
307+
308+
SI pixel= env->pixel;
309+
SI vgap = 0;
310+
if (env->get_string (PAGE_BORDER) == "none") {
311+
vgap= 4 * pixel;
312+
}
313+
array<box> pg= pages;
314+
if (env->get_string (PAGE_MEDIUM) == "paper")
311315
for (int i= 0; i < nx; i++)
312316
for (int j= 0; j < ny; j++) {
313317
int p= j * nx + i - d;
314318
if (p >= 0 && p < nr_pages) {
315-
SI l= 10 * pixel, r= 10 * pixel;
316-
SI b= 10 * pixel, t= 10 * pixel;
317-
if (env->get_string (PAGE_BORDER) == "attached") {
318-
#ifdef QTTEXMACS
319-
if (i > 0) l= pixel / 2;
320-
#else
319+
SI l= 0, r= 0, b= 0, t= 0;
320+
if (env->get_string (PAGE_BORDER) != "none") {
321+
l= 10 * pixel, r= 10 * pixel;
322+
b= 10 * pixel, t= 10 * pixel;
323+
if (env->get_string (PAGE_BORDER) == "attached") {
324+
if (i > 0) l= pixel / 2;
325+
if (i < nx - 1) r= 0;
326+
}
327+
}
328+
else {
321329
if (i > 0) l= pixel;
322-
#endif
323-
if (i < nx - 1) r= 0;
324330
}
325331
color bg= tm_background;
326332
if (env->get_string ("full-screen-mode") == "true") bg= black;
@@ -351,7 +357,8 @@ pager_rep::make_pages () {
351357
yy[j]= yy[j - 1];
352358
for (int i= 0; i < nx; i++) {
353359
int p= j * nx + i - d;
354-
if (p >= 0 && p < nr_pages) yy[j]= min (yy[j - 1] - pg[p]->h (), yy[j]);
360+
if (p >= 0 && p < nr_pages)
361+
yy[j]= min (yy[j - 1] - pg[p]->h () - vgap, yy[j]);
355362
}
356363
}
357364

0 commit comments

Comments
 (0)