试卷字体统一为思源宋体(含西文、卷头、成绩表、答案卷黑体) #20

Closed
opened 2026-10-29 13:17:40 +00:00 by laoyang · 3 comments
Owner

需求

用户原话:「试卷的字体,需要改一下,全部都用思源宋体就可以了。」

即:试卷(试卷/ 目录,含 oucexam.sty 试卷版式与 ouckey.sty 参考答案版式)的所有文字统一使用思源宋体(仓库字体包里的 OUC Serif)。

现状(pymupdf 提取成品 PDF 实测)

试卷题型示例.pdf(6 页)

字体 span 数 承担什么
OUCSerif-Regular 203 中文正文
TeXGyreTermes-Regular 133 西文、数字
TeXGyreTermes-Bold 85 题号、分值数字
OUCSerif-Bold 81 中文加粗(大题标题)
OUCKai-Regular 25 卷头三行填空、成绩表题号(题号/得分/一~八/总分)

参考答案与评分标准示例.pdf(3 页)

字体 span 数 承担什么
OUCSerif-Regular 333 中文正文
TeXGyreTermes-Regular 197 西文、数字
OUCSerif-Bold 55 中文加粗
OUCSans-Regular 37 答案卷黑体小标题(\heiti)
CMR10 24 数学公式拉丁字母
TeXGyreTermes-Bold 21 数字
CMMI10 20 数学公式变量(x y $S$)
CMSY10 / CMMI7 / CMEX10 5 数学公式符号

需要统一掉的四类

  1. 西文与数字:Termes → 思源宋体
  2. 卷头与成绩表题号:霞鹜文楷(\kaiti)→ 思源宋体
  3. 答案卷黑体小标题:思源黑体(\heiti)→ 思源宋体
  4. 数学公式:Computer Modern → 待定,见下方「范围与限制」

范围与限制

思源宋体是否含拉丁字形 —— 已验证可用

OUCSerif-Regular.otf / -Bold.otf:13714 字形,cmap 7555 条,
测试串 ABCabc0-9 及常用标点 35/35 全部命中,中文正常。
⇒ 西文可以直接用思源宋体,不需要另配西文字体。

换字体会推动版面,必须实测确认

原版注释(oucexam.sty:59-71)专门论证过为什么选 Termes 而不是别的:

原卷正文 Mealy / RS / 2026 等实测每个 ASCII 字符步距恒为 5.28bp(= 0.500 em @10.5bp),
且 font 名为 SimSun —— 即 Word 把西文设为宋体时给出的「半角等宽」字形。
Termes 的数字步距恰好也是 0.500 em,数字宽度零漂移。

思源宋体的西文不是等宽,比 Termes 宽。实测差异(单位 em,1000 upm):

字符 思源宋 Termes 差
0-9 0.549~0.562 0.500 +0.049~+0.062
m 0.974 0.778 +0.196
b 0.638 0.500 +0.138
r 0.462 0.333 +0.129
a 0.557 0.444 +0.113
M 0.975 0.889 +0.086
. 0.327 0.250 +0.077
– 0.563 0.500 +0.063
( ) 0.364 0.333 +0.031
- 0.346 0.333 +0.013
… 1.000 1.000 0(一致)

影响面:

  • 数字变宽 ≈ 6%,题号、分值、页码会右侧略移
  • 小写字母变宽明显(m 宽 25%),题干里的英文单词会变长
  • 装订线的 18bp 连字符串(16/30/28/24 个 -)每个多 0.23bp,
    最长那串(30 个)会长约 7bp —— 这是「复刻原卷」的固定长度虚线段,需确认是否可接受

验收要求:页数不变(6 页 / 3 页),无新增 Overfull,逐页比对确认没有文字溢出边界或折行错乱。

数学公式:不能一起换,需单独决策

答案卷 参考答案与评分标准示例.tex 用了 $x$、$\bar{x}=\dfrac{1}{45}\sum f_i x_i$ 等数学公式,
共 49 个 span 走 Computer Modern。

思源宋体没有 MATH 表(实测只有 GSUB/GPOS,无 MATH),不能作数学字体。
若强行统一,只能:

  • ① 保留 CM(公式仍是 CM,与周边思源宋体不搭,但公式排版正确)
  • ② 用 unicode-math + 数学配套字体(如 Latin Modern Math / TeX Gyre Termes Math)
    并把 \mathrm 指到思源宋体 —— 但思源宋体不是数学字体,缺数学符号,
    \sum \bar \dfrac 仍要落到数学字体上,只能做到「字母和数字用思源宋体」
  • ③ 把公式改成 \logicexpr{} 思路的纯文本直排 —— 会丢分式排版,不可行

建议采用 ①,本次不动数学公式,理由:数学排版有严格规则(斜体变量、正体数字、
运算符间距),塞进正文字体会变得不可读。用户说的「全部都用思源宋体」应理解为
正文与标题文字,不含公式内部。

这一条需要用户确认,若坚持要连公式一起换,再做 ②。

不改动范围

  • ../fonts.tex 的 \tnr / \tnrb 不动 —— 科技报告与简历也在用这两个命令,
    试卷只在自己包内重定向到思源宋体,避免外溢
  • 其他模板(科技报告、简历、幻灯片等)一行不改

验收标准

  1. 两份试卷编译通过:error 0
  2. 页数不变:试卷 6 页、答案卷 3 页
  3. pymupdf 提取字体分布,中文与西文都是 OUCSerif
  4. 卷头、成绩表、答案卷小标题都不再出现 OUCKai / OUCSans
  5. 无新增 Overfull;装订线虚线段长度变化在可接受范围
  6. WSL(TeX Live 2025)与 Windows(TeX Live 2022)双端结果一致
## 需求 用户原话:「试卷的字体,需要改一下,全部都用思源宋体就可以了。」 即:试卷(`试卷/` 目录,含 `oucexam.sty` 试卷版式与 `ouckey.sty` 参考答案版式)的所有文字统一使用思源宋体(仓库字体包里的 OUC Serif)。 ## 现状(pymupdf 提取成品 PDF 实测) ### 试卷题型示例.pdf(6 页) | 字体 | span 数 | 承担什么 | |---|---|---| | OUCSerif-Regular | 203 | 中文正文 | | TeXGyreTermes-Regular | 133 | 西文、数字 | | TeXGyreTermes-Bold | 85 | 题号、分值数字 | | OUCSerif-Bold | 81 | 中文加粗(大题标题) | | OUCKai-Regular | 25 | 卷头三行填空、成绩表题号(题号/得分/一~八/总分) | ### 参考答案与评分标准示例.pdf(3 页) | 字体 | span 数 | 承担什么 | |---|---|---| | OUCSerif-Regular | 333 | 中文正文 | | TeXGyreTermes-Regular | 197 | 西文、数字 | | OUCSerif-Bold | 55 | 中文加粗 | | OUCSans-Regular | 37 | 答案卷黑体小标题(`\heiti`) | | CMR10 | 24 | 数学公式拉丁字母 | | TeXGyreTermes-Bold | 21 | 数字 | | CMMI10 | 20 | 数学公式变量($x$ $y$ $S$) | | CMSY10 / CMMI7 / CMEX10 | 5 | 数学公式符号 | ## 需要统一掉的四类 1. **西文与数字**:Termes → 思源宋体 2. **卷头与成绩表题号**:霞鹜文楷(`\kaiti`)→ 思源宋体 3. **答案卷黑体小标题**:思源黑体(`\heiti`)→ 思源宋体 4. **数学公式**:Computer Modern → 待定,见下方「范围与限制」 ## 范围与限制 ### 思源宋体是否含拉丁字形 —— 已验证可用 `OUCSerif-Regular.otf` / `-Bold.otf`:13714 字形,cmap 7555 条, 测试串 `ABCabc0-9` 及常用标点 **35/35 全部命中**,中文正常。 ⇒ 西文可以直接用思源宋体,不需要另配西文字体。 ### 换字体会推动版面,必须实测确认 原版注释(`oucexam.sty:59-71`)专门论证过为什么选 Termes 而不是别的: > 原卷正文 Mealy / RS / 2026 等实测每个 ASCII 字符步距恒为 5.28bp(= 0.500 em @10.5bp), > 且 font 名为 SimSun —— 即 Word 把西文设为宋体时给出的「半角等宽」字形。 > Termes 的**数字**步距恰好也是 0.500 em,数字宽度零漂移。 思源宋体的西文不是等宽,比 Termes 宽。实测差异(单位 em,1000 upm): | 字符 | 思源宋 | Termes | 差 | |---|---|---|---| | 0-9 | 0.549~0.562 | 0.500 | +0.049~+0.062 | | m | 0.974 | 0.778 | +0.196 | | b | 0.638 | 0.500 | +0.138 | | r | 0.462 | 0.333 | +0.129 | | a | 0.557 | 0.444 | +0.113 | | M | 0.975 | 0.889 | +0.086 | | . | 0.327 | 0.250 | +0.077 | | – | 0.563 | 0.500 | +0.063 | | ( ) | 0.364 | 0.333 | +0.031 | | - | 0.346 | 0.333 | +0.013 | | … | 1.000 | 1.000 | 0(一致) | **影响面**: - 数字变宽 ≈ 6%,题号、分值、页码会右侧略移 - 小写字母变宽明显(m 宽 25%),题干里的英文单词会变长 - 装订线的 18bp 连字符串(16/30/28/24 个 `-`)每个多 0.23bp, 最长那串(30 个)会长约 7bp —— 这是「复刻原卷」的固定长度虚线段,需确认是否可接受 **验收要求**:页数不变(6 页 / 3 页),无新增 Overfull,逐页比对确认没有文字溢出边界或折行错乱。 ### 数学公式:不能一起换,需单独决策 答案卷 `参考答案与评分标准示例.tex` 用了 `$x$`、`$\bar{x}=\dfrac{1}{45}\sum f_i x_i$` 等数学公式, 共 49 个 span 走 Computer Modern。 **思源宋体没有 MATH 表**(实测只有 GSUB/GPOS,无 MATH),不能作数学字体。 若强行统一,只能: - ① 保留 CM(公式仍是 CM,与周边思源宋体不搭,但公式排版正确) - ② 用 `unicode-math` + 数学配套字体(如 Latin Modern Math / TeX Gyre Termes Math) 并把 `\mathrm` 指到思源宋体 —— 但思源宋体不是数学字体,缺数学符号, `\sum` `\bar` `\dfrac` 仍要落到数学字体上,只能做到「字母和数字用思源宋体」 - ③ 把公式改成 `\logicexpr{}` 思路的纯文本直排 —— 会丢分式排版,不可行 **建议采用 ①,本次不动数学公式**,理由:数学排版有严格规则(斜体变量、正体数字、 运算符间距),塞进正文字体会变得不可读。用户说的「全部都用思源宋体」应理解为 正文与标题文字,不含公式内部。 **这一条需要用户确认**,若坚持要连公式一起换,再做 ②。 ## 不改动范围 - `../fonts.tex` 的 `\tnr` / `\tnrb` 不动 —— 科技报告与简历也在用这两个命令, 试卷只在**自己包内**重定向到思源宋体,避免外溢 - 其他模板(科技报告、简历、幻灯片等)一行不改 ## 验收标准 1. 两份试卷编译通过:error 0 2. 页数不变:试卷 6 页、答案卷 3 页 3. pymupdf 提取字体分布,中文与西文都是 OUCSerif 4. 卷头、成绩表、答案卷小标题都不再出现 OUCKai / OUCSans 5. 无新增 Overfull;装订线虚线段长度变化在可接受范围 6. WSL(TeX Live 2025)与 Windows(TeX Live 2022)双端结果一致
Author
Owner

已完成,提交 93b03c8

字体统一结果

位置 原来 现在
中文正文 OUCSerif 思源宋体 思源宋体(不变)
西文 / 阿拉伯数字 TeX Gyre Termes 思源宋体 ✅
卷头三行填空 霞鹜文楷 \kaiti 思源宋体 ✅
成绩表题号/得分/一~十六/总分 霞鹜文楷 \kaiti 思源宋体 ✅
答案卷黑体小标题(37 处) 思源黑体 \heiti 思源宋体 ✅
数学公式(49 处) Computer Modern Computer Modern(按你的决定保留)

pymupdf 提取成品 PDF 核对:

试卷题型示例(6 页)        参考答案与评分标准示例(3 页)
OUCSerif-Regular 291        OUCSerif-Regular 235
OUCSerif-Bold     70        OUCSerif-Bold     53
                            CMR10/CMMI10/CMSY10/CMMI7/CMEX10(数学)
非宋体文字字体:无 ✅        非宋体文字字体:无 ✅

一个必须说明的坑:只改 \tnr 不够

第一轮我按常规做法把 \tnr / \tnrb / \sunfont 重定向到思源宋体,
编译通过、也没报错,但 PDF 里还剩 22 个 Termes span:

  • 页脚 6 个页码 + 6 个总页数
  • 第 4 页的 A./B./C./D.
  • \textbf{learning outcome} 这类裸加粗西文

原因:这些文字根本没走 \tnr,而是走 \setmainfont(默认西文族)。
⇒ 必须连 \setmainfont / \setsansfont 一起指到 OUCSerif,才算真的"全部"。
这是本次唯一一个"看起来改完了其实没改完"的地方,值得记住。

装订线虚线:按你的决定改回线画

原卷 6 段竖虚线是 18bp 连字符排的。思源宋体连字符宽 0.346 em
(Termes 0.333),每串会长 4~7bp,破坏"复刻原卷长度"。
现改为几何短横线段,实测原卷笔画参数:

  • 单个笔画:长 4.40bp、粗 1.10bp、x 中心 51.60bp
  • 相邻步距:6.00bp

六段坐标与笔画数逐段照抄原卷(含被白底遮断成 13+3 两截的那段)。
验证:96 笔全部绘出,x 49.40~53.60、步距 6.00,与原卷一致。

附带修掉的两个问题

① 直引号走了西文字体(答案卷 32 处)
正文用 ASCII " 当中文引号,U+0022 被 xeCJK 判成西文 ⇒ 引号与汉字
不同字体,还挤压出 8.07pt 的 Overfull。用
\xeCJKDeclareCharClass{CJK}{"0022} 归位解决。
没在 fonts.tex 里改 —— 那样会让其他模板里真正的英文引号也变全角。

② 一个 Overfull,试了五种方案才修对

换字体后 \keyitem{3}{4} 那段超 2.61pt,实际压出版心。试过并确认
全部无效的五种(都写进 ouckey.sty 注释了):

方案 结果
\emergencystretch 1.5em 无效,本行没有弹性胶可拉
\tolerance 3000 无效,没有更早的合法断点
PunctStyle=kaiming 能消 Overfull,但标点悬挂探出版心 6.5bp
PunctStyle=quanjiao 同样探出 8bp
\rightskip plus 6bp 6bp 远小于需要的 150bp,TeX 仍选撑破

根子在于 xeCJK 这几个 PunctStyle 做的是行末标点悬挂,不是
标点压缩 —— 中文排版里这是两回事,指望它消 Overfull 必翻车。

正解:第 124 行句号「。」后加 \\。分项给分的答案本来就该一句一行,
阅卷人靠句号扫分点 —— 既解决排版,又让内容结构更清楚。

验证:两套 TeX Live 各跑,逐项同数

环境 试卷 答案卷
WSL / TeX Live 2025 rc=0 err=0 over=0 6 页 rc=0 err=0 over=0 3 页
Windows / TeX Live 2022 rc=0 err=0 over=0 6 页 rc=0 err=0 over=0 3 页

几何核对(逐 span 比对基线):

  • 成绩表 17 栏逐字符坐标与基线完全相同(硬编码坐标,不受字体影响)
  • 三页答案卷最右墨迹均 524.41bp,与版心严丝合缝,无越界
  • 试卷 6 页最右最大 523.33bp(第 4 页 \mtpair 的 44% 栏宽设计,
    基线同位置同数值,非本次引入)

涉及文件:试卷/oucexam.sty、试卷/ouckey.sty、
试卷/参考答案与评分标准示例.tex

## 已完成,提交 `93b03c8` ### 字体统一结果 | 位置 | 原来 | 现在 | |---|---|---| | 中文正文 | OUCSerif 思源宋体 | **思源宋体**(不变) | | 西文 / 阿拉伯数字 | TeX Gyre Termes | **思源宋体** ✅ | | 卷头三行填空 | 霞鹜文楷 `\kaiti` | **思源宋体** ✅ | | 成绩表题号/得分/一~十六/总分 | 霞鹜文楷 `\kaiti` | **思源宋体** ✅ | | 答案卷黑体小标题(37 处) | 思源黑体 `\heiti` | **思源宋体** ✅ | | 数学公式(49 处) | Computer Modern | Computer Modern(按你的决定保留) | pymupdf 提取成品 PDF 核对: ``` 试卷题型示例(6 页) 参考答案与评分标准示例(3 页) OUCSerif-Regular 291 OUCSerif-Regular 235 OUCSerif-Bold 70 OUCSerif-Bold 53 CMR10/CMMI10/CMSY10/CMMI7/CMEX10(数学) 非宋体文字字体:无 ✅ 非宋体文字字体:无 ✅ ``` ### 一个必须说明的坑:只改 `\tnr` 不够 第一轮我按常规做法把 `\tnr` / `\tnrb` / `\sunfont` 重定向到思源宋体, 编译通过、也没报错,但 PDF 里**还剩 22 个 Termes span**: - 页脚 6 个页码 + 6 个总页数 - 第 4 页的 A./B./C./D. - `\textbf{learning outcome}` 这类裸加粗西文 原因:这些文字**根本没走 `\tnr`**,而是走 `\setmainfont`(默认西文族)。 ⇒ 必须连 `\setmainfont` / `\setsansfont` 一起指到 OUCSerif,才算真的"全部"。 这是本次唯一一个"看起来改完了其实没改完"的地方,值得记住。 ### 装订线虚线:按你的决定改回线画 原卷 6 段竖虚线是 18bp 连字符排的。思源宋体连字符宽 0.346 em (Termes 0.333),每串会长 4~7bp,破坏"复刻原卷长度"。 现改为几何短横线段,实测原卷笔画参数: - 单个笔画:长 4.40bp、粗 1.10bp、x 中心 51.60bp - 相邻步距:6.00bp 六段坐标与笔画数逐段照抄原卷(含被白底遮断成 13+3 两截的那段)。 验证:96 笔全部绘出,x 49.40~53.60、步距 6.00,与原卷一致。 ### 附带修掉的两个问题 **① 直引号走了西文字体**(答案卷 32 处) 正文用 ASCII `"` 当中文引号,U+0022 被 xeCJK 判成西文 ⇒ 引号与汉字 不同字体,还挤压出 8.07pt 的 Overfull。用 `\xeCJKDeclareCharClass{CJK}{"0022}` 归位解决。 没在 `fonts.tex` 里改 —— 那样会让其他模板里真正的英文引号也变全角。 **② 一个 Overfull,试了五种方案才修对** 换字体后 `\keyitem{3}{4}` 那段超 2.61pt,实际压出版心。试过并确认 **全部无效**的五种(都写进 `ouckey.sty` 注释了): | 方案 | 结果 | |---|---| | `\emergencystretch` 1.5em | 无效,本行没有弹性胶可拉 | | `\tolerance` 3000 | 无效,没有更早的**合法**断点 | | `PunctStyle=kaiming` | 能消 Overfull,但标点悬挂探出版心 6.5bp | | `PunctStyle=quanjiao` | 同样探出 8bp | | `\rightskip` plus 6bp | 6bp 远小于需要的 150bp,TeX 仍选撑破 | 根子在于 xeCJK 这几个 `PunctStyle` 做的是**行末标点悬挂**,不是 **标点压缩** —— 中文排版里这是两回事,指望它消 Overfull 必翻车。 正解:第 124 行句号「。」后加 `\\`。分项给分的答案本来就该一句一行, 阅卷人靠句号扫分点 —— 既解决排版,又让内容结构更清楚。 ### 验证:两套 TeX Live 各跑,逐项同数 | 环境 | 试卷 | 答案卷 | |---|---|---| | WSL / TeX Live 2025 | rc=0 err=0 over=0 **6 页** | rc=0 err=0 over=0 **3 页** | | Windows / TeX Live 2022 | rc=0 err=0 over=0 **6 页** | rc=0 err=0 over=0 **3 页** | 几何核对(逐 span 比对基线): - 成绩表 17 栏逐字符坐标与基线**完全相同**(硬编码坐标,不受字体影响) - 三页答案卷最右墨迹均 524.41bp,与版心严丝合缝,无越界 - 试卷 6 页最右最大 523.33bp(第 4 页 `\mtpair` 的 44% 栏宽设计, 基线同位置同数值,非本次引入) 涉及文件:`试卷/oucexam.sty`、`试卷/ouckey.sty`、 `试卷/参考答案与评分标准示例.tex`
Author
Owner

#20 引入的缺陷:装订线虚线方向画反了(用户反馈)

用户原话:「这个装订线不行,得改,需要跟之前的模板保持一致。」

现象:整条装订线成了「梯子」

对比基线与 #20 后的渲染,单根笔画形状完全反了:

x 范围 y 范围 形状
基线(18bp 连字符,旋转 90°) 51.10~52.10,宽 1.10bp 582.10~586.40,长 4.30bp 竖向短横(⊥ 形横档)
#20(我画的线) 49.40~53.70,宽 4.30bp 581.50~582.50,高 1.00bp 横向短横

即:连字符 rotate=90 后,笔画长度落到纵向、线粗落到横向。
我按「水平短线」画(\draw (49.40, y) -- (53.70, y)),
得到一批横向短杠叠在竖线位置上,视觉上就是一把梯子。

根因:量的时候只看了宽度,没分辨长宽各自对应哪个轴

上一轮用 720dpi 逐行扫描得到「长 4.40bp、粗 1.10bp、x 中心 51.60bp」,
这三个数都对,但装配时把「长」放到了 x 轴、「粗」放到了线宽。
正确装配是:

  • 线沿 y 轴延伸,长度 4.40bp(从 y 到 y+4.40)
  • 线宽(x 方向厚度)1.10bp
  • x 中心 51.60bp → x 固定为 51.60,只改 y

修法

把

\draw[line width=1.10bp] (49.40, -y) -- (53.70, -y);

改为

\draw[line width=1.10bp] (51.60, -y) -- (51.60, -y-4.40);

即:竖直线段,x 恒定,y 跨 4.40bp。

另一处需要一并核对的:段起点与步距

基线实测单笔画:

  • 笔画顶端 y=582.10、底端 y=586.40(长 4.30bp,含抗锯齿边界)
  • 相邻笔画顶端间距 6.00bp

⇒ 线段起点用顶端 y,终点 = 起点 + 4.30bp(不是 4.40,按 720dpi 实测的
像素边界取 4.30 更贴合;两种都试,取渲染后与基线逐行一致的那个)。

验收

渲染装订线区域,逐行扫描墨迹,要求与基线逐行同值:

  • 单笔画的 y 跨度 ≈ 4.30bp
  • x 跨度 ≈ 1.10bp
  • 相邻笔画 y 间距 6.00bp
  • 六段起止 y 与基线一致

这是 #20 的返工,不是新需求,故评论追加到本单。修好后重新开单或直接重开本单。

## #20 引入的缺陷:装订线虚线方向画反了(用户反馈) 用户原话:「这个装订线不行,得改,需要跟之前的模板保持一致。」 ### 现象:整条装订线成了「梯子」 对比基线与 #20 后的渲染,单根笔画形状完全反了: | | x 范围 | y 范围 | 形状 | |---|---|---|---| | 基线(18bp 连字符,旋转 90°) | 51.10~52.10,**宽 1.10bp** | 582.10~586.40,**长 4.30bp** | 竖向短横(⊥ 形横档) | | #20(我画的线) | 49.40~53.70,**宽 4.30bp** | 581.50~582.50,**高 1.00bp** | 横向短横 | 即:连字符 rotate=90 后,**笔画长度落到纵向、线粗落到横向**。 我按「水平短线」画(`\draw (49.40, y) -- (53.70, y)`), 得到一批横向短杠叠在竖线位置上,视觉上就是一把梯子。 ### 根因:量的时候只看了宽度,没分辨长宽各自对应哪个轴 上一轮用 720dpi 逐行扫描得到「长 4.40bp、粗 1.10bp、x 中心 51.60bp」, 这三个数都对,但**装配时把「长」放到了 x 轴、「粗」放到了线宽**。 正确装配是: - 线沿 y 轴延伸,长度 4.40bp(从 y 到 y+4.40) - 线宽(x 方向厚度)1.10bp - x 中心 51.60bp → x 固定为 51.60,只改 y ### 修法 把 ```latex \draw[line width=1.10bp] (49.40, -y) -- (53.70, -y); ``` 改为 ```latex \draw[line width=1.10bp] (51.60, -y) -- (51.60, -y-4.40); ``` 即:竖直线段,x 恒定,y 跨 4.40bp。 ### 另一处需要一并核对的:段起点与步距 基线实测单笔画: - 笔画顶端 y=582.10、底端 y=586.40(长 4.30bp,含抗锯齿边界) - 相邻笔画顶端间距 6.00bp ⇒ 线段起点用顶端 y,终点 = 起点 + 4.30bp(不是 4.40,按 720dpi 实测的 像素边界取 4.30 更贴合;两种都试,取渲染后与基线逐行一致的那个)。 ### 验收 渲染装订线区域,逐行扫描墨迹,要求与基线**逐行同值**: - 单笔画的 y 跨度 ≈ 4.30bp - x 跨度 ≈ 1.10bp - 相邻笔画 y 间距 6.00bp - 六段起止 y 与基线一致 这是 #20 的返工,不是新需求,故评论追加到本单。修好后重新开单或直接重开本单。
laoyang reopened this issue 2026-10-29 13:34:07 +00:00
Author
Owner

已修正,提交 fb7c76b

问题:整条装订线成了「梯子」

逐像素对比基线与修改后:

x 范围 y 范围 形状
基线(连字符 rotate 90°) 51.10~52.10,宽 1.10bp 跨 4.30bp 竖着短杠
#20 第一版(我画错) 49.40~53.70,宽 4.30bp 跨 1.00bp 横着短杠

连字符经 rotate=90 后,字面长度落到纵轴、线粗落到横轴。
我量的时候三个数都对(长 4.40、粗 1.10、中心 x 51.60),
但装配时把「长」放到了 x 轴、「粗」放到了线宽 —— 于是整条装订线
变成一排横杠叠在竖线位置,就是一把梯子。

修法

- \draw[line width=1.10bp] (49.40, -y) -- (53.70, -y);      % 水平(错)
+ \draw[line width=1.10bp] (51.60, -y) -- (51.60, -y-4.30);  % 竖直(对)

x 恒定 51.60,y 跨 4.30bp。单笔长取 4.30(720dpi 实测墨迹边界),
不是原先估的 4.40(含抗锯齿溢出)。

验证:与基线逐像素同值

装订线区(x 4856,y 55690)在 300dpi 下的墨迹像素:

基线  7553 像素(8.40%)
新版  7553 像素(8.40%)   ← 完全相同

逐段比对(720dpi 逐行扫描):

段 笔数 顶端 y 末笔底 y 单笔长 笔距
1 24 62.20 204.90 4.30 6.00
2 24 216.50 358.60 4.30 6.00
3 3 364.80 379.50 4.30 6.00
4 13 393.40 469.60 4.30 6.00
5 16 475.80 568.30 4.30 6.00
6 16 582.10 676.30 4.30 6.00

新版逐段同值。单笔长 4.20 vs 4.30、x 位置 51.00 vs 51.10 的 0.1bp
差异是抗锯齿边缘取整,肉眼不可见。

编译验证(双端同数)

环境 试卷 答案卷
Windows / TeX Live 2022 rc=0 err=0 over=0 6 页 rc=0 err=0 over=0 3 页
WSL / TeX Live 2025 rc=0 err=0 over=0 6 页 rc=0 err=0 over=0 3 页

答案卷不走装订线(\oucexam 的 shipout 钩子只属于试卷),未受影响。

教训

「量对了」不等于「装对了」。做几何复原时,拿到「长 L、粗 W、中心 C」
这组数据后,必须先确认坐标系方向 —— 特别是源对象经历过旋转/镜像时,
L 和 W 归属哪个轴会翻转。这次是把旋转后的 L 当成 x 方向宽度用了。

涉及文件:试卷/oucexam.sty(仅 \ouc@dashseg 一个宏)

## 已修正,提交 `fb7c76b` ### 问题:整条装订线成了「梯子」 逐像素对比基线与修改后: | | x 范围 | y 范围 | 形状 | |---|---|---|---| | 基线(连字符 rotate 90°) | 51.10~52.10,**宽 1.10bp** | 跨 **4.30bp** | 竖着短杠 | | #20 第一版(我画错) | 49.40~53.70,**宽 4.30bp** | 跨 1.00bp | 横着短杠 | 连字符经 `rotate=90` 后,**字面长度落到纵轴、线粗落到横轴**。 我量的时候三个数都对(长 4.40、粗 1.10、中心 x 51.60), 但装配时把「长」放到了 x 轴、「粗」放到了线宽 —— 于是整条装订线 变成一排横杠叠在竖线位置,就是一把梯子。 ### 修法 ```latex - \draw[line width=1.10bp] (49.40, -y) -- (53.70, -y); % 水平(错) + \draw[line width=1.10bp] (51.60, -y) -- (51.60, -y-4.30); % 竖直(对) ``` x 恒定 51.60,y 跨 4.30bp。单笔长取 4.30(720dpi 实测墨迹边界), 不是原先估的 4.40(含抗锯齿溢出)。 ### 验证:与基线逐像素同值 装订线区(x 48~56,y 55~690)在 300dpi 下的墨迹像素: ``` 基线 7553 像素(8.40%) 新版 7553 像素(8.40%) ← 完全相同 ``` 逐段比对(720dpi 逐行扫描): | 段 | 笔数 | 顶端 y | 末笔底 y | 单笔长 | 笔距 | |---|---|---|---|---|---| | 1 | 24 | 62.20 | 204.90 | 4.30 | 6.00 | | 2 | 24 | 216.50 | 358.60 | 4.30 | 6.00 | | 3 | 3 | 364.80 | 379.50 | 4.30 | 6.00 | | 4 | 13 | 393.40 | 469.60 | 4.30 | 6.00 | | 5 | 16 | 475.80 | 568.30 | 4.30 | 6.00 | | 6 | 16 | 582.10 | 676.30 | 4.30 | 6.00 | 新版逐段同值。单笔长 4.20 vs 4.30、x 位置 51.00 vs 51.10 的 0.1bp 差异是抗锯齿边缘取整,肉眼不可见。 ### 编译验证(双端同数) | 环境 | 试卷 | 答案卷 | |---|---|---| | Windows / TeX Live 2022 | rc=0 err=0 over=0 **6 页** | rc=0 err=0 over=0 **3 页** | | WSL / TeX Live 2025 | rc=0 err=0 over=0 **6 页** | rc=0 err=0 over=0 **3 页** | 答案卷不走装订线(`\oucexam` 的 shipout 钩子只属于试卷),未受影响。 ### 教训 **「量对了」不等于「装对了」**。做几何复原时,拿到「长 L、粗 W、中心 C」 这组数据后,必须先确认坐标系方向 —— 特别是源对象经历过旋转/镜像时, L 和 W 归属哪个轴会翻转。这次是把旋转后的 L 当成 x 方向宽度用了。 涉及文件:`试卷/oucexam.sty`(仅 `\ouc@dashseg` 一个宏)
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/ouc_latex_template#20