用户要求:「试卷的字体,需要改一下,全部都用思源宋体就可以了。」 pymupdf 提取两份成品 PDF 定位到四类需要统一的字体: 试卷题型示例(6 页) 参考答案与评分标准示例(3 页) OUCSerif-Regular 203 中文 OUCSerif-Regular 333 中文 TeXGyreTermes-Regular 133 西文 TeXGyreTermes-Regular 197 西文 TeXGyreTermes-Bold 85 题号分值 OUCSans-Regular 37 黑体小标题 OUCSerif-Bold 81 中文加粗 CMR10/CMMI10/CMSY10 49 数学公式 OUCKai-Regular 25 卷头与成绩表 TeXGyreTermes-Bold 21 数字 一、西文与数字:Termes → 思源宋体(oucexam.sty / ouckey.sty) 先在包里用 \newfontfamily 登记 \OUCLatinSerif / \OUCLatinSerifBold (四个档位全给,斜体指回 Regular —— 思源宋体没有真斜体),再把 \tnr / \tnrb / \sunfont 都 \let 过去。 ⚠️ 只做这一步**不够**,这点踩了一轮:模板里大量文字根本没走 \tnr, 而是走 \setmainfont(默认西文族)——\textbf{learning outcome} 的裸西文、 页脚的页码与总页数、任何 \selectfont 之后的裸 ASCII。 第一轮只 \let 时,PDF 里仍残留 22 个 TeXGyreTermes span: 页脚 6 个页码 + 6 个总页数 + 第 4 页的 A./B./C./D. 与 learning outcome 等。 ⇒ 必须连 \setmainfont / \setsansfont 一起指到 OUCSerif。 二、卷头与成绩表题号:霞鹜文楷 → 思源宋体(oucexam.sty) \kh 与 \scoretable 用 \kaiti。包里 \let\kaiti\songti 一次性收口, 不动 ../fonts.tex 的 \def\kaiti —— 别的模板还要用楷体。 三、答案卷黑体小标题:思源黑体 → 思源宋体(ouckey.sty) \heiti 共 37 处(卷头大标题与各节小标题)。同样 \let\heiti\songti。 四、数学公式:保持不动 $x$ / $\dfrac{1}{45}\sum f_i x_i$ 等 49 处仍走 Computer Modern。 思源宋体没有 MATH 表(实测只有 GSUB/GPOS),不能作数学字体; 强行塞进正文字体会破坏斜体变量、正体数字、运算符间距。用户已确认。 五、装订线虚线:连字符排字 → 用线画(oucexam.sty) 原卷那 6 段竖虚线是 18bp Times 连字符排出来的。换成思源宋体后连字符 每个宽 0.346 em(Termes 0.333),每串会长 4~7bp,破坏"复刻原卷长度"。 ⇒ 改为几何画的短横线段,长度锁死。实测原卷(720dpi 逐笔画测量): 单个连字符笔画 长 4.40bp、粗 1.10bp、x 中心 51.60bp 相邻笔画步距 6.00bp 新增 \ouc@dashseg{起点y}{笔画数},六段坐标与笔画数逐段照抄原卷 (含原卷被白底遮断成 13+3 两截的那一段)。 ⚠️ \newcommand 必须定义在 \ouc@dobindstrip 外面,否则每次 shipout 重新定义,第二页起报 already defined。 ⚠️ y 坐标不能写 \dimexpr#1bp+\i*6bp —— TikZ 坐标解析器不认小数 + \dimexpr 组合,报 Illegal unit of measure。要先 \pgfmathsetmacro。 六、直引号归入 CJK(ouckey.sty) 答案卷正文用 ASCII 直引号 "" 表示中文引号(32 处)。U+0022 在 Basic Latin,xeCJK 判为西文 ⇒ 引号走 \setmainfont,与两侧汉字不同字体, 并挤压出 Overfull(第 88 行 +8.07pt)。 \xeCJKDeclareCharClass{CJK}{"0022} 归位后解决。 ⚠️ 不在 fonts.tex 里改:那里全库共用,会让正文真正的英文引号(代码 片段 "hello world")也变全角。 七、Overfull 的修法:改源码断行,不调参数(ouckey.sty 留有完整记录) 换字体后 \keyitem{3}{4} 那段 Overfull 2.61pt,实际压出版心 (最右 527.01bp,版心止于 524.41)。试过并确认**全部无效**的五种: · \emergencystretch 1.5em —— 本行没有弹性胶可拉,无从施展 · \tolerance 3000 —— 不是不满意断点,是没有更早的合法断点 · PunctStyle=kaiming —— 能消 Overfull,但标点悬挂探出版心 6.5bp · PunctStyle=quanjiao —— 同样探出 8bp (xeCJK 这几个 PunctStyle 做的是"标点悬挂"不是"标点压缩", 指望它消 Overfull 必翻车) · \rightskip 0pt plus 6bp(含 \AtBeginDocument 版)—— 6bp 远小于 需要的 150bp,TeX 仍选"撑破"这个解 正解:第 124 行句号「。」后加 \\。分项给分的答案本来就该一句一行, 读者靠句号扫分点 —— 既解决排版,又让内容结构更清楚。 验证(两套环境各跑,逐项同数) 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页 pymupdf 提取字体分布: 试卷题型示例 OUCSerif-Regular 291 + OUCSerif-Bold 70 → 非宋体文字字体:无 参考答案示例 OUCSerif-Regular 235 + OUCSerif-Bold 53 + CMR10/CMMI10/CMSY10/CMMI7/CMEX10(数学,保留) → 非宋体文字字体:无 几何核对(逐 span 比对,均与基线一致或更优): · 成绩表 17 栏逐字符坐标与基线**完全相同**(硬编码坐标,不受字体影响) · 装订线 96 笔全部绘出:x 49.40~53.60(宽 4.40bp)、步距 6.00bp, 六段位置与原卷实测一致 · 三页最右墨迹均为 524.41bp,与版心严丝合缝,无越界 · 试卷 6 页最右最大 523.33bp(第 4 页 \mtpair 的 44% 栏宽设计, 基线同位置同样数值,非本次引入) 涉及文件: 试卷/oucexam.sty 默认族、西文字族、\kaiti、装订线虚线 试卷/ouckey.sty 默认族、西文字族、\heiti、直引号、踩坑记录 试卷/参考答案与评分标准示例.tex 第 124 行句号后加断行
试卷 —— 试卷与参考答案 LaTeX 模板
中国海洋大学期末考试试卷与参考答案及评分标准的 XeLaTeX 模板。 两份模板均不含真题,题目与分值都是示意,按教学大纲替换即可。
样张是《数字逻辑》2025 秋的一份完整虚构 A 卷:16 类题型(填空 / 选择 / 判断 / 化简 / 分析 / 设计 / 时序 / 计数器 / 状态机 / 存储器 / ADC-DAC / Verilog / 综合设计 …)+ 对应参考答案与评分标准(8 大题 / 满分 100)。 题目是按数字逻辑课程内容真编的、答案算过是对的,不是「略」或「×××」—— 这样既能看清版式,也能看出各题型的排版难度(比如卡诺图、时序波形图 都是 TikZ 内联画的)。
与
课程教学日历/、成绩构成说明/、试卷归档封面/是同一门课,四份一起看是自洽的。 唯一故意留空的是命题人 / 审核人 / 各题得分栏 —— 那是要签字担责的, 编名字上去容易被误当真实署名。
文件
| 文件 | 说明 |
|---|---|
oucexam.sty |
试卷版式包。纸张 195×270mm(学校专用试卷纸),含装订栏、成绩表、页脚 |
ouckey.sty |
答案与评分标准版式包。默认 A4;加 exampaper 选项则与试卷同纸同边距 |
试卷题型示例.tex |
试卷范例,16 类题型,6 页 |
参考答案与评分标准示例.tex |
答案范例,8 大题 / 满分 100,3 页 |
编译
xelatex 试卷题型示例.tex
xelatex 试卷题型示例.tex # 跑两遍,第二遍才能取到正确总页数(lastpage)
必须用 XeLaTeX(fontspec + xeCJK),pdflatex 编译不过。 两份 .tex 都在本目录内自包含,不依赖任何图片文件(示例配图是 TikZ 内联画的)。
试卷模板要点
纸张、页边距、行距、装订栏位置、页脚样式都已在 oucexam.sty 里按原卷实测值定好,
一般只改 \examsetup 那一块(下例是样张实际用的虚构值):
\examsetup{
year = {2025}, % 学年(会自动印成 2025—2026)
term = {秋}, % 秋 / 春
course = {数字逻辑},
college = {信息科学与工程学院},
type = {A}, % 卷头「试卷类型:A 卷」
foottype = {}, % 页脚课程名后是否再印类型字母,空=不印
proposer = {}, % 命题人
reviewer = {}, % 审核人
mode = {闭卷},
allowed = {无}, % 允许携带的物品
nsec = {16}, % 大题数,成绩表自动按 nsec+1 栏等分
}
proposer/reviewer样张里故意留空:命题人、审核人是要签字担责的, 编一个名字上去容易被误当真实署名。留空时模板自动不印该项、不留空横线。type与foottype互不影响:前者只管卷头,后者只管页脚。 原卷 A 卷页脚没印字母、B 卷印了 B,这是出卷人手工差异,不是规则。- 大题数变了必须同步改
nsec,否则成绩表格子会错位。
答案模板要点
\keysetup{
year = {2025}, term = {秋}, course = {数字逻辑}, type = {A},
dept = {计算机科学与技术学院}, college = {信息科学与工程学院},
major = {计算机科学与技术专业 \TNR{2023} 级},
teacher = {张远航}, examiner = {张远航},
mode = {闭卷、笔试}, total = {100},
}
如实现在试卷同一张纸上印,把 \usepackage{ouckey} 改成 \usepackage[exampaper]{ouckey}。
体例四条(学校没有统一模板,按国内高校通行做法拟定):
- 抬头信息齐全,留空的项自动不印、不留空横线
- 客观题答案集中列(
\objkeys{C,B,A,...},每行 6 个自动换行),附统一给分规则 - 主观题内嵌分步分值(
\pt{2}),阅卷时批到哪里看到哪里 - 每个大题末尾给【评分标准】
\scoring{...}
主观题内嵌分值是有意为之:阅卷是流水作业,分值必须和答案文字贴在一起, 集中写在末尾会让批卷人来回翻页。
文末 \keytotal{20,10,12,12,12,16,8,10} 是分值汇总表,用于阅卷前核对
「各大题相加 = 满分」。签名栏 \keysign 只留命题人一处。
书写注意
- 题干内部换行用
\\*,不要用裸\\。裸\\语义是"允许在此断页", 题干会被切到上下两页,学生看到半句话。 - 数字、英文用
\TNR{...}包起来(内部显式\normalfont收尾)。 裸用字体切换命令会让字体状态泄漏到后续段落。 \keyitem{题号}{分值}{答案正文}的参数里不要嵌tabular/tikzpicture—— 这些环境的&与\\会被当成参数分隔符,报File ended while scanning。 表格和图写在\keyitem之后。