Skip to content

Fixed a bug of "makespa"#756

Merged
Liam0205 merged 18 commits intoCTeX-org:masterfrom
myhsia:master
Apr 30, 2026
Merged

Fixed a bug of "makespa"#756
Liam0205 merged 18 commits intoCTeX-org:masterfrom
myhsia:master

Conversation

@myhsia
Copy link
Copy Markdown
Contributor

@myhsia myhsia commented Dec 3, 2025

Windows / *nix 上在制作 .spa 时都会出现如下错误

396438169f41f729a6ad8bd91a7fbd4c

正确用法的_影子_可在 xetex 文档 pp. 10 查到:
xetex manual \font\x="[CharisSIL-Italic.ttf]" at 24pt \x

具体复现与 Debug 细节,可参见 LaTeX 技术交流群记录(对于任何字体都会有,包括 fandol

@Explorer-cc 的讨论

@myhsia:
这个涉及到-shell-escape编组问题,i.e. 比如 win 上若文件名有-,则文件名需要"",而macOS则需要''

问题复现

  1. 安装最新版lxgw-fonts
  2. clone ctex-kit
  3. cd 到 ctex-kit/ctex
  4. 执行 l3build unpack
  5. 把抽取的 a. ctex-spa-macro.tex; b. ctex-spa-make.tex 临时放一个文件夹
  6. 在 ctex-spa-make.tex 添加这组“键值对(不严谨地讲,其实更像 l3case)”,并把其他内容注释掉(毕竟你不可能安装了所有系统字体)
    {lxgwzhsong}      {LXGWWenKaiLite-Regular} ,
    {lxgwzhsongb}     {LXGWWenKaiLite-Medium} ,
    {lxgwzhhei}       {LXGWMarkerGothic-Regular} ,
    {lxgwzhfs}        {LXGWXiaolai-Regular} ,
    {lxgwzhkai}       {LXGWYozai-Regular} ,
    {lxgwzhkaib}      {LXGWYozai-Medium} ,
  1. 命令行执行 xelatex -shell-escape ./ctex-spa-make.tex,看看是否会 font not found, \scan_stop:
  2. 无论会不会,将 ctex-spa-macro.tex 文件的 line 55 更改为:
\tex_font:D \l__ctex_punct_font = "[#2]" ~ at ~ 100 pt \scan_stop:

也就是把 "#2" 改为 "[#2]"
9. 再次执行 xelatex -shell-escape ./ctex-spa-make.tex,看看是否会得到报错/报错消失
10. 已知 macOS 需要这样更改,Windows 是否需要未知

此处省略部分问答

@Explorer-cc: 「7. 命令行执行 xelatex -shell-escape ./ctex-spa-make.tex,看看是否会 font not found, \scan_stop:

这里的报错日志见 4 楼 @Explorer-cc 贴出的.

@Explorer-cc: 「8. 无论会不会,将 ctex-spa-macro.tex 文件的 line 55 更改为:
\tex_font:D \l__ctex_punct_font = "[#2]" ~ at ~ 100 pt \scan_stop:
也就是把 "#2" 改为 "[#2]"
9. 再次执行 xelatex -shell-escape ./ctex-spa-make.tex,看看是否会得到报错/报错消失」
6e1a813baad038e46af5a2eb91f24b6c
报错消失了

@myhsia: 截图下目录中的 .spa 文件内容,我顺便比对下两个系统生成的spa数据是否一致

@Explorer-cc: .spa 内容

简述解决方法:注意到 xetex manual \font\x="[CharisSIL-Italic.ttf]" at 24pt \x 中的 "[字体文件]" 这种代码格式,over.

@muzimuzhi
Copy link
Copy Markdown
Member

muzimuzhi commented Dec 3, 2025

所以是,之前的字体名刚好都不包含 -?好奇为什么之前能用。

(引用内容时,建议文字形式优先;实在要发图片时,建议保持图片比例一致,这样图里的文字大小也一致)

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Dec 4, 2025

之前的 macro 那个文件确实不包含那个方括号,我猜测应该是 -shell-escape 执行的脚本对应的程序在某个时间点更新了什么东西…

@Explorer-cc
Copy link
Copy Markdown

Explorer-cc commented Dec 4, 2025

(引用内容时,建议文字形式优先;实在要发图片时,建议保持图片比例一致,这样图里的文字大小也一致)

支持,文字形式的内容更容易被搜索引擎检索到(考虑到后来人需要检索类似错误时带来的便利性)。

第一幅图的文本形式内容(在windows11上测试的结果)为:

xelatex --shell-escape ctex-spa-make
This is XeTeX, Version 3.141592653-2.6-0.999997 (TeX Live 2025) (preloaded format=xelatex)
 \write18 enabled.
entering extended mode
(./ctex-spa-make.tex
LaTeX2e <2025-11-01>
L3 programming layer <2025-11-14>
(./ctex-spa-macro.tex
(c:/texlive/2025/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
(c:/texlive/2025/texmf-dist/tex/latex/l3kernel/expl3.sty
(c:/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-xetex.def))))
kpathsea: Running mktextfm LXGWXiaolai-Regular

The command name is C:\texlive\2025\bin\windows\mktextfm

kpathsea: Running mktexmf LXGWXiaolai-Regular.mf

The command name is C:\texlive\2025\bin\windows\mktexmf
name = LXGWXiaolai-Regular, rootname = LXGWXiaolai-Regular, pointsize = 
mktexmf: empty or non-existent rootfile!
Cannot find LXGWXiaolai-Regular.mf.
kpathsea: Appending font creation commands to missfont.log.

! Font \l__ctex_punct_font=LXGWXiaolai-Regular at 100.0pt not loadable: Metric  
(TFM) file or installed font not found.
<to be read again>
                   \scan_stop:
l.86   }

?

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Dec 4, 2025

BTW, make 文件中 fandolcases 的字体名有误, 缺少一些 -Regular. 我已在 macOS 测试, @Explorer-cc 已在 Windows 上测试. 就不新开 PR 了, 一起合并好了

对话记录:

@myhsia @北回归线-Explorer E 老师有时间可在 Windows 上再帮我测试一个类似的 case:
<此处省略一万字>

  1. 注释掉 ctex-spa-make.tex\MAKESPA {ctexpunct.spa} 的所有内容,只保留 {fandolzh*} 开头的 6 行 cases
  2. 命令行执行 xetex -shell-escape ./ctex-spa-make.tex
    也会相同报错
  3. 把 fandol 的6行替换为
    {fandolzhsong}    {FandolSong-Regular} ,
    {fandolzhsongb}   {FandolSong-Bold} ,
    {fandolzhhei}     {FandolHei-Regular} ,
    {fandolzhheib}    {FandolHei-Bold} ,
    {fandolzhkai}     {FandolKai-Regular} ,
    {fandolzhfs}      {FandolFang-Regular} ,

并再次命令行编译,如果顺利通过并生成 .spa 文件,发下 .spa 文件内容

@Explorer-cc
「1. 注释掉 ctex-spa-make.tex\MAKESPA {ctexpunct.spa} 的所有内容,只保留 {fandolzh*} 开头的 6 行 cases
2. 命令行执行

  xetex -shell-escape ./ctex-spa-make.tex

也会相同报错」
同样报错

@Explorer-cc
a2d988596d7f358ce919ca7487350e87

其实就是是这个脚本旧了,以至于 Fandol 字体 filename 更新,这里都没来得及更新 :-)

e5651290b1d45164d747978a251367ee

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Dec 4, 2025

BTW, make 文件中 fandolcases 的字体名有误, 缺少一些 -Regular. 我已在 macOS 测试, @Explorer-cc 已在 Windows 上测试. 就不新开 PR 了, 一起合并好了

Fixed in Commit #be574c4

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Dec 4, 2025

BTW, make 文件中 fandolcases 的字体名有误, 缺少一些 -Regular. 我已在 macOS 测试, @Explorer-cc 已在 Windows 上测试. 就不新开 PR 了, 一起合并好了

补充:

@Explorer-cc 执行的起点是? 改不改 「#2」「[#2]」

@myhsia 改.

这说明这个 bug 是普遍性的,针对任何字体,包括 fandol.

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Dec 6, 2025

BTW, make 文件中 fandolcases 的字体名有误, 缺少一些 -Regular. 我已在 macOS 测试, @Explorer-cc 已在 Windows 上测试. 就不新开 PR 了, 一起合并好了

补充:

@Explorer-cc 执行的起点是? 改不改 「#2」「[#2]」

@myhsia 改.

这说明这个 bug 是普遍性的,针对任何字体,包括 fandol.

Hope to merge asap.
This bug may block some font developers from developing the ctex-fontset file :-D

@Liam0205
Copy link
Copy Markdown
Contributor

Review

感谢 @myhsia@Explorer-cc 的调查和测试!问题确实存在,但第一处修改有回归风险,需要调整。

Fandol 文件名修正:✅ 没问题

FandolSongFandolSong-Regular 等四处修正与当前 Fandol 字体包的实际文件名一致,纯粹的事实修正。

字体加载语法 "#2""[#2]"⚠️ 有回归风险

XeTeX 中 "FontName" 是按字体名通过 fontconfig/系统查找,"[filename]" 是按文件名通过 kpathsea 查找。这两种机制适用于不同的字体来源。

当前字体列表(ctex.dtx:11695-11750)混合了两种类型的条目:

类型 示例 "#2" "[#2]"
TeX 目录树字体 FandolSong-Regular, FZShuSong-Z01 可能失败 ✅ kpathsea 查文件
系统字体(含空格) Songti SC Light, Noto Serif CJK SC, Microsoft YaHei, HYShuSongEr S ✅ fontconfig 查名称 ❌ 找不到同名文件

改为 "[#2]" 会修复 TeX 目录树字体(Fandol、LXGW 等),但会破坏所有系统字体条目(macOS、Ubuntu、Windows、汉仪),因为 kpathsea 找不到名为 Songti SC Light.otfMicrosoft YaHei.otf 的文件。

CI 三平台通过是因为 CI 不测试 SPA 生成(手动操作),仅测试使用已有 .spa 文件的编译结果。

建议

需要一个能同时处理两种字体来源的方案,例如:

  • 为两类条目使用不同的加载路径
  • 或统一将所有条目转为其中一种形式(但系统字体的文件名跨平台不一致,难以统一为文件名)

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026

@Liam0205 在 #62cefa5 中, 我添加了一个判断: 如果当前字体 (是的, 我还做了 .ttf.off 两种扩展名测试, 感觉应该很完备了) 在 kpsewhich 下返回内容, 则存在; 否则如果返回 blank, 则不存在, 那么就是系统字体, 然后我更改了 \@@__write_family:nn, 在里面加入了判断, 从额决定调用 kpsewhich 还是 fontconfig.

我只有 macOS, 所以只测试了 fandolmacnew, 生成 spa 良好; 只是这样会导致 shell 的输出有些啰嗦烦人, 但是也无所谓. 这里贴上运行 xetex ctex-spa-make.tex 的结果:

(base) myhsia@Mingyus-iMac unpacked % xetex ctex-spa-make.tex
This is XeTeX, Version 3.141592653-2.6-0.999998 (TeX Live 2026) (preloaded format=xetex)
 restricted \write18 enabled.
entering extended mode
(./ctex-spa-make.tex (./ctex-spa-macro.tex
(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3-code.tex)
(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-xetex.def)))
(|kpsewhich FandolSong-Regular.otf) (|kpsewhich FandolSong-Regular.ttf)
(|kpsewhich FandolSong-Bold.otf) (|kpsewhich FandolSong-Bold.ttf)
(|kpsewhich FandolHei-Regular.otf) (|kpsewhich FandolHei-Regular.ttf)
(|kpsewhich FandolHei-Bold.otf) (|kpsewhich FandolHei-Bold.ttf)
(|kpsewhich FandolKai-Regular.otf) (|kpsewhich FandolKai-Regular.ttf)
(|kpsewhich FandolFang-Regular.otf) (|kpsewhich FandolFang-Regular.ttf)
(|kpsewhich Songti SC Light.otf) (|kpsewhich Songti SC Light.ttf)
(|kpsewhich Songti SC Bold.otf) (|kpsewhich Songti SC Bold.ttf)
(|kpsewhich Heiti SC Medium.otf) (|kpsewhich Heiti SC Medium.ttf)
(|kpsewhich Heiti SC Light.otf) (|kpsewhich Heiti SC Light.ttf)
(|kpsewhich Kaiti SC.otf) (|kpsewhich Kaiti SC.ttf)
(|kpsewhich Kaiti SC Bold.otf) (|kpsewhich Kaiti SC Bold.ttf)
(|kpsewhich STFangsong.otf) (|kpsewhich STFangsong.ttf)
(|kpsewhich Baoli SC.otf) (|kpsewhich Baoli SC.ttf)
(|kpsewhich Yuanti SC Light.otf) (|kpsewhich Yuanti SC Light.ttf)
(|kpsewhich Yuanti SC Regular.otf) (|kpsewhich Yuanti SC Regular.ttf)
(|kpsewhich PingFang SC.otf) (|kpsewhich PingFang SC.ttf)
(|kpsewhich PingFang SC Semibold.otf) (|kpsewhich PingFang SC Semibold.ttf) )
No pages of output.
Transcript written on ctex-spa-make.log.
(base) myhsia@Mingyus-iMac unpacked % 

@Explorer-cc 如果有时间的话你也可以测试一下 Windows 下的表现, 只保留 fandol 类和 windows 类, 其他的行注释掉后运行 xetex.

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026

顺便替换了几处 Guard: \g__ctex_.. -> \g_@@_...

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026

@Liam0205 我在手册的 implementation 里简要描述了这个判断的函数, 并写了 \change 更新记录. 日期、版本号你需要后续根据情况修改; 我的文笔不太好, 具体文本描述你也可以稍加修改.

@Liam0205
Copy link
Copy Markdown
Contributor

顺便替换了几处 Guard: \g__ctex_.. -> \g_@@_...

我好像记得有几个位置是故意没用 @@ 来着。

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026 via email

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026

顺便替换了几处 Guard: \g__ctex_.. -> \g_@@_...

我好像记得有几个位置是故意没用 @@ 来着。

image

我改的是1万多行外的, 而这个 guard 是在 4923 -- 6564 行范围内, 所以没问题

@myhsia
Copy link
Copy Markdown
Contributor Author

myhsia commented Apr 30, 2026

@Liam0205 新增函数的 implementation 部份排版已完成, actions 已通过
image

@Liam0205 Liam0205 merged commit 877809e into CTeX-org:master Apr 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants