diff --git a/TeXmacs/progs/generic/document-menu.scm b/TeXmacs/progs/generic/document-menu.scm index 083d8f703c..f18f4d8efd 100644 --- a/TeXmacs/progs/generic/document-menu.scm +++ b/TeXmacs/progs/generic/document-menu.scm @@ -936,6 +936,7 @@ ("Palette" (interactive-background set-background '())) ("Pattern" (open-pattern-selector set-background "1cm")) ("Gradient" (open-gradient-selector set-background)) + ("Picture" (open-background-picture-selector set-background)) ("Other" (init-interactive-env "bg-color")) ) ;menu-bind diff --git a/TeXmacs/progs/generic/pattern-selector.scm b/TeXmacs/progs/generic/pattern-selector.scm index 7bef1c11e5..b2f83509a0 100644 --- a/TeXmacs/progs/generic/pattern-selector.scm +++ b/TeXmacs/progs/generic/pattern-selector.scm @@ -19,22 +19,41 @@ ;; Name conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define (pattern-name->url s) + ;; 兼容旧版本写入的 /C/Users/... 路径。 + (if (and (os-windows?) + (>= (string-length s) 3) + (== (string-ref s 0) #\/) + (char-alphabetic? (string-ref s 1)) + (== (string-ref s 2) #\/) + ) ;and + (system->url (string-append (substring s 1 2) ":" (substring s 2 (string-length s))) + ) ;system->url + (unix->url s) + ) ;if +) ;define + +(define (pattern-url->name u) + ;; 用正斜杠避免 Windows 反斜杠破坏偏好设置的 Scheme 语法。 + (if (os-windows?) (string-replace (url->system u) "\\" "/") (url->unix u)) +) ;define + (define (encode-pattern-name u) (let* ((name (if (string? u) u (url->unix u))) (t (url->unix (url-tail u))) (p (url->unix "$TEXMACS_PATH/misc/patterns")) (a (url->unix "$TEXMACS_PATH/misc")) - (p* (url-append (unix->url p) "dummy")) - (a* (url-append (unix->url a) "dummy")) + (p* (url-append (pattern-name->url p) "dummy")) + (a* (url-append (pattern-name->url a) "dummy")) ) ; - (cond ((string-starts? name p) (url->unix (url-delta p* (unix->url name)))) + (cond ((string-starts? name p) (url->unix (url-delta p* (pattern-name->url name)))) (else u) ) ;cond ) ;let* ) ;define (define (decode-pattern-name s) - (let* ((name (unix->url s)) + (let* ((name (pattern-name->url s)) (base1 "$TEXMACS_PATH/misc/patterns/neutral-pattern.png") (base2 "$TEXMACS_PATH/misc/pictures/gradients/vertical-white-black.png") (base (if global-gradient? base2 base1)) @@ -239,7 +258,12 @@ ) ;define (define (normalize-color col) - (if (tm-func? col 'pattern) (apply tm-pattern (cdr col)) col) + ;; 图片选择器已经将本地路径规范化为可写入文档的 Unix 形式。 + ;; 再经 tm-pattern 转为系统路径会在 Windows 偏好项中留下反斜杠。 + (if (and (tm-func? col 'pattern) (not global-picture?)) + (apply tm-pattern (cdr col)) + col + ) ;if ) ;define ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -247,16 +271,16 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (tm-widget (pattern-name-selector) - (let* ((name (unix->url (get-name))) + (let* ((name (pattern-name->url (get-name))) (curr (decode-pattern-name (get-name))) (setter (lambda (c) (when (and (pair? c) (url? (car c))) - (set-name (url->unix (car c))) + (set-name (pattern-url->name (car c))) ) ;when ) ;lambda ) ;setter ) ; - (hlist (enum (set-name (url->unix answer)) + (hlist (enum (set-name (pattern-url->name answer)) (list `(verbatim ,(url->system name)) "") `(verbatim ,(url->system name)) "15em" @@ -269,7 +293,7 @@ (choose-file setter "Background pattern" "image" "" curr) ) ; (global-gradient? (choose-file setter "Background gradient" "image" "" curr)) - ((url-rooted? (unix->url (get-name))) + ((url-rooted? (pattern-name->url (get-name))) (choose-file setter "Background picture" "image" "" curr) ) ; (else (choose-file setter "Background picture" "image")) diff --git a/devel/2090.md b/devel/2090.md index dcd3927a0c..cbfb12a005 100644 --- a/devel/2090.md +++ b/devel/2090.md @@ -99,3 +99,38 @@ tmu 格式下 pattern 第一个参数(图片链接)以 UTF-8 原样落盘 ### 8.4 涉及文件 - `TeXmacs/progs/generic/document-menu.scm` + +## 9 恢复文档背景图片入口(2026-08-12) + +### 做什么 +恢复“文档 -> 颜色 -> 背景色 -> 图片”菜单项。 + +### 原因 +背景图片选择器仍可生成合法的三参数 `pattern`,但排查期间入口被临时隐藏,用户无法使用该功能。 + +### 实现方式 +在 `document-background-color-menu` 中恢复已有的 +`open-background-picture-selector` 动作。 + +### 涉及文件 +- `TeXmacs/progs/generic/document-menu.scm` + +## 10 修复 Windows 背景图片路径(2026-08-12) + +### 做什么 +使背景图片选择器在 Windows 下能够预览并应用本地图片。 + +### 原因 +文件对话框返回的系统路径若直接写入偏好设置,会包含反斜杠并导致 Scheme 解析失败; +而将其写为 `/C/...` 又无法被系统路径解析器识别为 Windows 盘符路径。 + +### 实现方式 +选择器将 Windows 图片保存为 `C:/...`:该形式可由 `url_system` 识别,且只使用正斜杠, +能够安全写入 Scheme 偏好设置。预览和正式渲染优先通过 `url_system` 解析,同时保留对旧版 +Unix 形式路径的回退。背景图片不再重复经过 `tm-pattern`,避免确认时再次生成反斜杠。 + +### 涉及文件 +- `TeXmacs/progs/generic/pattern-selector.scm` +- `src/Graphics/Renderer/brush.cpp` +- `src/Typeset/Env/env_exec.cpp` +- `tests/Graphics/Renderer/brush_test.cpp` diff --git a/src/Graphics/Renderer/brush.cpp b/src/Graphics/Renderer/brush.cpp index f413053faf..03cafc05e1 100644 --- a/src/Graphics/Renderer/brush.cpp +++ b/src/Graphics/Renderer/brush.cpp @@ -108,9 +108,15 @@ url brush_rep::get_pattern_url () { tree t= get_pattern (); if (is_atomic (t) || N (t) == 0 || !is_atomic (t[0])) return url (); - url u= url_system (as_string (t[0])); + string name= as_string (t[0]); + // 选择器保存的 C:/ 路径须经系统解析器识别为盘符路径。 + url u= url_system (name); url r= resolve_pattern (u); if (!is_none (r)) return r; + // 保持对旧版 Unix 形式路径的兼容。 + u= url_unix (name); + r= resolve_pattern (u); + if (!is_none (r)) return r; #if defined(KERNEL_L3) url base= url_pwd (); #else diff --git a/src/Typeset/Env/env_exec.cpp b/src/Typeset/Env/env_exec.cpp index 2b9a14ea78..917fa12d7f 100644 --- a/src/Typeset/Env/env_exec.cpp +++ b/src/Typeset/Env/env_exec.cpp @@ -2059,7 +2059,9 @@ tree edit_env_rep::exec_pattern (tree t) { if (N (t) < 1) return tree (ERROR, "bad pattern"); if (no_patterns && N (t) == 4 && is_atomic (t[3])) return exec (t[3]); - url im= url_system (exec_string (t[0])); + string name= exec_string (t[0]); + // 选择器保存的 C:/ 路径须经系统解析器识别为盘符路径。 + url im= url_system (name); url image; if (is_none (base_file_name)) { image= resolve_pattern (im); @@ -2067,6 +2069,16 @@ edit_env_rep::exec_pattern (tree t) { else { image= resolve_pattern (relative (base_file_name, im)); } + if (is_none (image)) { + // 保持对旧版 Unix 形式路径的兼容。 + im= url_unix (name); + if (is_none (base_file_name)) { + image= resolve_pattern (im); + } + else { + image= resolve_pattern (relative (base_file_name, im)); + } + } if (is_none (image)) return "white"; int imw_pt, imh_pt; image_size (image, imw_pt, imh_pt); diff --git a/tests/Graphics/Renderer/brush_test.cpp b/tests/Graphics/Renderer/brush_test.cpp index f93bcb083b..4a8d3f3e7d 100644 --- a/tests/Graphics/Renderer/brush_test.cpp +++ b/tests/Graphics/Renderer/brush_test.cpp @@ -13,6 +13,7 @@ #include "base.hpp" #include "brush.hpp" +#include "tm_url.hpp" #include #include @@ -28,6 +29,7 @@ private slots: void test_atomic_color (); void test_pattern_three_args (); void test_pattern_four_args (); + void test_pattern_system_url (); void test_malformed_patterns (); }; @@ -50,6 +52,15 @@ TestBrush::test_pattern_four_args () { QCOMPARE (brush (p)->get_type (), brush_pattern); } +void +TestBrush::test_pattern_system_url () { +#if defined(OS_MINGW) || defined(OS_WIN) + url picture= url_system ("C:/Users/test/Picture.png"); + QCOMPARE (as_string (picture, URL_SYSTEM), + string ("C:\\Users\\test\\Picture.png")); +#endif +} + void TestBrush::test_malformed_patterns () { // 缺宽度/高度参数:绘制时会读取 p[1]/p[2],必须回退 no_brush