Files
ouc_latex_template/fonts.tex
T
laoyang 69da5b41a6 简历排版修正:项目经验整块右移、西文换 Cochineal、课程执行大纲漏网 × #12
一、项目经验整块右移(简历/awesome-source-cv.cls)
  \rightcolumnlength 算早了:geometry 的 1.5cm 边距要到导言区结束才生效,
  cls 里那句 \setlength 读到 article 默认 \textwidth=345pt,算出 249.87pt,
  比应有的 417.02pt 少 167.15pt。longtable 把窄表居中排,整块右移 83.6pt。
  修法:计算挪进 \AtBeginDocument 并减去 | 竖线的 \arrayrulewidth;
  R 列由 >{\hfill}m{2.5cm} 改为 >{\raggedright\arraybackslash}p{2.5cm}。
  日期左边缘 145.1 -> 48.5pt,与其余章节严格对齐。
  这类错误零 error 零 warning,只能量 PDF 坐标才能发现。

二、西文换 Cochineal(fonts/cochineal/ + fonts.tex + 简历 cls)
  中文思源宋体配 Termes 时西文笔画偏细,中英混排会「陷进去」。
  Cochineal 宽 225.42pt vs Termes 229.68pt,只窄 1.9%,断行位置基本不动;
  Pagella/XCharter 宽 7~11%,会把全库断行推着变,故不选。
  字体 920KB 入 fonts/cochineal/(SIL OFL 1.1,附 OFL.txt),
  fonts.tex 新增 \oucUseCochineal 开关,只简历调用,其余 10 个模板不受影响。

三、换字体后暴露的真实缺陷
  西文窄 1.9% 让断点整体前移,ICIEA 那条论文冲出 88.49pt(文字顶到纸边)。
  根因是中文紧跟英文的位置不是断开点,整串被当长单词。
  加 \emergencystretch=3em 解决。

四、课程执行大纲漏网占位符(ouccourse.sty)
  ××学部××学院 硬编码在 \ccschool 里,#11 只扫了 .tex 没扫 .sty 所以漏了。
  拆成 \ccdepartment / \cccollege 两个名称宏,默认「信息科学与工程学部 /
  计算机科学与技术学院」。重编后全文 × 归零。

「代码库 PDF 没更新」经核实不成立:本地/远程 HEAD 均为 8984b93,
从服务器下载 8 个 PDF 逐字节比对全部一致,简历.pdf 3 页 0 个 ×。

验证:简历 3 页 0 error/0 Overfull/0 Underfull;全库 12 项编译回归与基线一致。
2026-10-27 13:13:54 +08:00

388 lines
18 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
%======================================================================
% oucfonts.tex —— 中国海洋大学模板库的公共字体入口
%
% 本文件是仓库内**唯一**允许声明字体的地方。十一个模板全部通过
% \input{../fonts.tex}
% 取字体,不再各自写 \setCJKmainfont / \setmainfont。
%
% 为什么是 .tex + \input 而不是 .sty + \usepackage:
% \usepackage 走 LaTeX 的 package 机制,要求 \ProvidesPackage 的名字
% 与 \usepackage 的参数严格一致。我们从子目录用相对路径调用
% (\usepackage{../oucfonts}),名字必然对不上,会报
% "You have requested package `../oucfonts' but the package provides
% `oucfonts'." 的警告。用 \input 直接插入文件内容,没有这个问题,
% 而且对宏包加载顺序的控制也更直接。
%
% ------------------------------------------------------------------
% 用法
% ------------------------------------------------------------------
% \documentclass[UTF8,fontset=none]{ctexart}
% \input{../fonts.tex}
%
% ⚠️ 必须保留 fontset=none:否则 ctex 会先按系统字体配一套,
% 再被这里覆盖,既浪费又有平台依赖。
%
% ⚠️ Path=../fonts/ 是相对**模板目录**的(编译时的工作目录)。
% 在本模板目录下 xelatex 编译即可,不要从仓库根调用。
%
% ------------------------------------------------------------------
% 提供的字族命令
% ------------------------------------------------------------------
% \songti 宋体(衬线正文) OUC Serif ← 思源宋体 SC 子集
% \heiti 黑体(无衬线标题) OUC Sans ← 思源黑体 SC 子集
% \kaiti 楷体 OUC Kai ← 霞鹜文楷子集
% \fangsong 仿宋 Zhuque Fangsong ← 朱雀仿宋
% \tnr 西文 Times 等价 TeX Gyre Termes
% \tnrb 西文 Times 粗体 TeX Gyre Termes Bold
% \hm 鸿蒙 Sans SC 幻灯片/科技报告 原有字体
% \hmlatin 鸿蒙 Sans(西文) 幻灯片/科技报告 原有字体
%
% 正文字体:中文 OUC Serif,西文 TeX Gyre Termes。
%
% 本文件**可重复** \input(用 \ifdefined 保护),方便多个 .sty 各自引用。
%
% ------------------------------------------------------------------
% 字体来源与授权(全部允许免费商用与再分发)
% ------------------------------------------------------------------
% OUC Serif / OUC Sans 思源宋体/黑体 SC 的 GB2312 子集,
% Adobe 原版 SIL OFL 1.1。改名以符合 OFL §3
% (原 Reserved Font Name 为 "Source")。
% OUC Kai 霞鹜文楷 GB2312 子集,SIL OFL 1.1。
% Zhuque Fangsong 朱雀仿宋,OFL 1.1。
% TeX Gyre Termes GUST Font License(GPL + 字体例外)。
% HarmonyOS Sans 华为,官方声明可免费商用。
%
% 详细来源、版本与被裁剪的字符集见 fonts/README.md。
% **本模板库不含任何商业字体**(无方正、无 SimSun/SimHei/KaiTi/FangSong、
% 无 Times New Roman)。
%======================================================================
\ifdefined\OUCFontsLoaded
\endinput
\else
\def\OUCFontsLoaded{1}
\fi
\RequirePackage{fontspec}
\RequirePackage{xeCJK}
%======================================================================
% 一、西文主字体:TeX Gyre Termes(Times 的度量兼容开源替代)
%
% Termes 与 Times New Roman 字符宽度逐字相同,因此原有的西文断行、
% 表格列宽、行内公式对齐都不会因为换字体而漂。
%
% ⚠️ 全库默认就是 Termes。简历模板(简历/)单独换成 Cochineal,
% 见下面「一之二」。其余 10 个模板不受影响。
%======================================================================
\setmainfont{texgyretermes}[
Extension = .otf,
Path = ../fonts/tex-gyre-termes/,
UprightFont = *-regular,
BoldFont = *-bold,
ItalicFont = *-italic,
BoldItalicFont = *-bolditalic,
]
%======================================================================
% 一之二、西文备用字体:Cochineal(Minion 风格)
%
% 为什么加这一款:Termes 是 Times 的度量兼容替代,中文用思源宋体时,
% 两者笔画粗细与字面灰度差得比较明显 —— 汉字是宋体的中等粗细,
% 西文 Termes 偏细偏紧,中英混排时西文那一段会"陷进去"。
% Cochineal(Michael Sharpe 据 Minion 设计)笔画更饱满,与宋体灰度
% 接近,学术出版物里用得很广。
%
% 与 Termes 的度量差异(10pt 下同一句英文的排印宽度):
% Termes 229.68pt 100.0% x 高 0.450
% Cochineal 225.42pt 98.1% x 高 0.433
% 窄 1.9%,换过去几乎不会让断行位置变。这是选它而不是 Pagella
% (宽 10.8%)/ XCharter(宽 7.4%)的主要理由:那两款会把全库的
% 表格列宽和断行推着变。
%
% ⚠️ **不是全局生效**,必须显式调用下面这条才会切:
% \OUCLatinCochineal
% 目前只有 简历/awesome-source-cv.cls 调用。其余模板保持 Termes。
%
% ⚠️ 三个地方一起换才算真的换掉:
% ① \setmainfont —— 正文西文(正文里的英文、数字、DOI)
% ② \tnr / \tnrb —— 模板里显式用 Times 形态的地方
% ③ 数学字体 —— 本模板库的模板都不带公式,故未配 unicode-math。
% 若将来某个模板要用公式,得再补 \setmathfont,否则公式里的
% 拉丁字母还是 Computer Modern。
%
% 授权:SIL OFL 1.1(Copyright 2010-2014 Sebastian Kosch;
% 2016-2021 Michael Sharpe)。OFL.txt 已随字体放在
% ../fonts/cochineal/ 下。
%
% 度量数据(供将来换字体时对照,单位 1/1000 em,upm=1000):
% 字体 x 高 cap 高 x/cap A 宽 字重
% Termes 450 662 0.68 722 400
% Cochineal 433 649 0.67 612 400
%======================================================================
\newfontfamily\OUCLatinCochineal{cochineal}[
Extension = .otf,
Path = ../fonts/cochineal/,
UprightFont = *-Roman,
BoldFont = *-Bold,
ItalicFont = *-Italic,
BoldItalicFont = *-BoldItalic,
]
% 粗体专用档:对应上面 \tnrb 的语义("取粗体那一字形当常规用")。
% 与 \tnr 同样四档齐全,否则 \bfseries 里会报
% Font shape `TU/cochineal/b/n' undefined
% 并静默回落,表现是加粗失效。
\newfontfamily\OUCLatinCochinealBold{cochineal}[
Extension = .otf,
Path = ../fonts/cochineal/,
UprightFont = *-Bold,
BoldFont = *-Bold,
ItalicFont = *-BoldItalic,
BoldItalicFont = *-BoldItalic,
]
% 把上一条真正装成"正文西文字体"的开关。
% 单独做成命令而不在字体声明处直接 \setmainfont,是因为 \newfontfamily
% 只登记了一个字族;要让它接管正文,必须再用 \setmainfont 指过去。
\newcommand{\oucUseCochineal}{%
\setmainfont{cochineal}[
Extension = .otf,
Path = ../fonts/cochineal/,
UprightFont = *-Roman,
BoldFont = *-Bold,
ItalicFont = *-Italic,
BoldItalicFont = *-BoldItalic,
]%
% \tnr / \tnrb 也跟着走,否则模板里显式写了 \tnr 的地方仍是 Termes,
% 同一页出现两种西文字体。
\renewcommand{\tnr}{\OUCLatinCochineal}%
\renewcommand{\tnrb}{\OUCLatinCochinealBold}%
}
%======================================================================
% 二、中文主字体
%
% 宋体为正文,黑体为强调。二者的粗体都是字体自带的真粗体,
% 不再用 AutoFakeBold 算法描边 —— 描边出来的粗体笔画会糊在一起,
% 尤其小字号下(原模板 14pt 的宋体会糊成一团)。
%
% ⚠️ 这里用 \setCJKmainfont 而不是 \setCJKfamilyfont + \def:
% \setCJKmainfont 会顺带把 \CJKrmdefault 指到新族上,正文默认
% 字体才真的换过来。若文档是 ctex 默认 fontset,ctex 早已设过
% \CJKrmdefault,xeCJK 会打一条
% Package xeCJK Warning: Redefining CJKfamily `\CJKrmdefault'
% 这是**预期**行为(我们就是要覆盖 ctex 按系统字体配的那套),
% 不影响输出,也无害;看到它不必处理。
%
% ------------------------------------------------------------------
% 斜体与粗斜体:中文没有真正的斜体字形,中文排版惯例是「用楷体代
% 斜体、用仿宋代粗斜体」(《党政机关公文格式》与 Word 的中文默认
% 行为都是这么做的)。原科技报告模板正是
% ItalicFont = 方正楷体
% BoldItalicFont = 方正仿宋
% 这里保持同样的语义映射:楷体 → OUC Kai,仿宋 → Zhuque Fangsong。
%
% ⚠️ 各档位的字体在**不同目录**里,不能共用主选项的 Path/Extension。
% 必须在该档位的 *Features 里单独写一套 Path + Extension +
% UprightFont —— 主 Path 会被继承,若不在 Features 里覆盖,就会
% 拿 ../fonts/ouc-serif/ 去拼 OUCKai-Regular.ttf,报
% "The font "OUCKai-Regular" cannot be found"。
%
% ⚠️ 只在 \setCJKmainfont 上给了斜体,**不影响** \songti / \heiti /
% \kaiti / \fangsong 这几个字族命令 —— 它们是独立的字体族,各自
% 没有斜体档。要中文斜体就用默认正文(或先 \songti 再 \textit,
% 此时 \textit 落回 \CJKrmdefault 也就是 OUC Serif 的斜体)。
%======================================================================
\setCJKmainfont{OUCSerif}[
Extension = .otf,
Path = ../fonts/ouc-serif/,
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = OUCKai-Regular,
ItalicFeatures = {
Extension = .ttf,
Path = ../fonts/ouc-kai/,
UprightFont = *-Regular,
BoldFont = *-Bold,
},
BoldItalicFont = ZhuqueFangsong-Regular,
BoldItalicFeatures = {
Extension = .ttf,
Path = ../fonts/zhuque-fangsong/,
UprightFont = *-Regular,
},
]
% ------------------------------------------------------------------
% 小型大写(sc):用**字体形状替换**,不用 SmallCapsFont 选项
%
% 为什么需要它:简历模板的 \user / \resumetitle / \experience 都用了
% \textsc,而中文没有小型大写字形,不处理就每页刷 6 条
% LaTeX Font Warning: Font shape `TU/OUCSerif(0)/m/sc' undefined
% 惯例做法是让 sc 档**指回常规体**:\textsc{中文} 看起来不变(中文
% 本来也没有大小写),而 \textsc{English} 里的西文仍然走 \setmainfont
% 的 Termes 小型大写,行为正确。
%
% 为什么不写 SmallCapsFont —— 这里踩了整整一轮坑,结论留下免得重来:
%
% 1) SmallCapsFont 这个选项**与本文件上面的 ItalicFeatures /
% BoldItalicFeatures 互斥**。最小复现实测:
% 只有 SmallCapsFont + SmallCapsFeatures → 通过
% 再加 ItalicFeatures(带跨目录 Path) → 立刻报
% Package fontspec Error:
% The font "OUCSerif-Regular" cannot be found.
% 写 *-Regular、写全名 OUCSerif-Regular、写带 .otf 的、把两个键
% 挪到最后,全都报同一个错;把斜体换成同目录字体
% (ItalicFont = *-Bold)就又能过 —— 所以是**跨目录 Path 的相互作用**,
% 不是文件名写法问题。照着"IralicFont 怎么写的就怎么写"去改会一直失败。
%
% 2) 绕开的办法就是干脆不用那个选项,改用 LaTeX 原生的字体形状替换
% (\DeclareFontShape + <->ssub)。这条机制在 fontspec 选项之下,
% 不受选项间相互作用影响,效果完全等价。
%
% ⚠️ 第二个参数 OUCSerif(0) 里的 (0) 是 fontspec 给该字体生成的内部
% 族编号,不是笔误。若将来 \setCJKmainfont 换了字体名,这两行必须
% 同步改;写错**不会报错**,只会让 sc 警告悄悄回来 —— 改完看日志。
% ------------------------------------------------------------------
\DeclareFontShape{TU}{OUCSerif(0)}{m}{sc}{<->ssub * OUCSerif(0)/m/n}{}
\DeclareFontShape{TU}{OUCSerif(0)}{b}{sc}{<->ssub * OUCSerif(0)/b/n}{}
%======================================================================
% 三、字族命令
%
% ⚠️ 这里**不能**用 \newCJKfontfamily / \newfontfamily。
% 原因:只要文档用了 ctex 的默认 fontset(即 \documentclass 里没写
% fontset=none),ctex 就已经定义了 \songti / \heiti / \kaiti /
% \fangsong,而这两个命令底层是 LaTeX3 的 \NewDocumentCommand,
% 命令已存在时会抛
% ! LaTeX3 Error: Control sequence \songti already defined.
% 并**中断编译**(试卷/ouckey.sty 就是这种情况,报 4 个错误)。
% 用 \providecommand 先占位也没用 —— \newCJKfontfamily 仍然报。
%
% 正确写法分两步:
% 1. \setCJKfamilyfont{族名}[选项]{字体} 只登记字体,不建命令,
% 同名重复登记只是覆盖,永远不报错;
% 2. \def\songti{\CJKfamily{族名}} 纯 \def,从不管旧定义。
% 这也是 ctex 自己定义 \songti 的方式。
%======================================================================
% 宋体
\setCJKfamilyfont{OUCSong}[
Extension = .otf,
Path = ../fonts/ouc-serif/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCSerif}
\def\songti{\CJKfamily{OUCSong}}
% 黑体
\setCJKfamilyfont{OUCHei}[
Extension = .otf,
Path = ../fonts/ouc-sans/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCSans}
\def\heiti{\CJKfamily{OUCHei}}
% 楷体(霞鹜文楷)
% 顺带提供 \kaishu 别名:ctex 的默认 fontset 用 \kaishu,而原模板多用
% \kaiti,两个名字都指同一族,免得改接时漏改一处就静默回落系统字体。
\setCJKfamilyfont{OUCKai}[
Extension = .ttf,
Path = ../fonts/ouc-kai/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCKai}
\def\kaiti{\CJKfamily{OUCKai}}
\def\kaishu{\CJKfamily{OUCKai}}
% 仿宋(朱雀仿宋,只有常规一档,无粗体)
% ⚠️ 需要粗体的场合请改用 \heiti 或 \songti,不要指望 \fangsong 变粗。
\setCJKfamilyfont{OUCFang}[
Extension = .ttf,
Path = ../fonts/zhuque-fangsong/,
UprightFont = *-Regular,
]{ZhuqueFangsong}
\def\fangsong{\CJKfamily{OUCFang}}
% 西文:显式取 Times 形态(原模板里 \tnr / \tnrb / \sunfont 的替代)
%
% ⚠️ 四个档位必须全给。只给 UprightFont 的话,在 \bfseries 环境里会落到
% "Font shape `TU/texgyretermes/b/n' undefined" 并静默替换,
% 表现为加粗失效(试卷的 \TNRB 与 \qnum 都会踩到)。
\newfontfamily\tnr{texgyretermes}[
Extension = .otf,
Path = ../fonts/tex-gyre-termes/,
UprightFont = *-regular,
BoldFont = *-bold,
ItalicFont = *-italic,
BoldItalicFont = *-bolditalic,
]
\newfontfamily\tnrb{texgyretermes}[
Extension = .otf,
Path = ../fonts/tex-gyre-termes/,
UprightFont = *-bold,
BoldFont = *-bold,
ItalicFont = *-bolditalic,
BoldItalicFont = *-bolditalic,
]
% 鸿蒙 Sans:幻灯片与科技报告原有字体,保留以维持这两个模板的原有观感
% ⚠️ 鸿蒙的文件名以下划线分隔(HarmonyOS_Sans_SC_Regular.ttf),
% 不是 OHM 风格的 "族名-字重",所以这里不能写 *-Regular 通配,
% 必须显式给完整文件名。
% ⚠️ 用了 UprightFont 就**不要**再给主参数 {字体名}。给了两个,fontspec
% 会把主参数当文件名、UprightFont 当变体名再拼一次,报
% "The font HarmonyOS_Sans_SC_Regular.ttf cannot be found"。
% 正确写法是只留主参数(下面这种),或用 Extension + UprightFont。
\setCJKfamilyfont{OUCHM}[
Path = ../fonts/harmonyos-sans/,
BoldFont = HarmonyOS_Sans_SC_Bold.ttf,
]{HarmonyOS_Sans_SC_Regular.ttf}
\def\hm{\CJKfamily{OUCHM}}
\newfontfamily\hmlatin{HarmonyOS_Sans_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
BoldFont = HarmonyOS_Sans_Bold.ttf,
ItalicFont = HarmonyOS_Sans_Regular_Italic.ttf,
BoldItalicFont = HarmonyOS_Sans_Bold_Italic.ttf,
]
%======================================================================
% 四、把几个「长得像西文、其实该走中文」的符号归入 CJK 字符类
%
% 顺序很重要:必须在 \setCJKmainfont 之后、正文开始之前。
% 下面这些 \xeCJKDeclareCharClass 是**全局**生效的,一次即可。
%
% 为什么要这么做:xeCJK 按 Unicode 区段分类,下面这些字符落在
% Latin-1 / General Punctuation / Geometric Shapes,默认都被判成
% **西文**,交给 fontspec 的西文字体(Termes)。后果有两层:
% ① 宽度错:× 在 SimSun/思源里本来是 1.0 em 全角,被当西文排
% 就只剩 0.56 em,与汉字不齐、基线也偏(\heiti{××} 尤其明显);
% ② 缺字:□(U+25A1)Termes 里根本没有,直接报
% "Missing character: There is no □ (U+25A1)",印出来是空白。
% 而 \heiti / \fangsong 只切 CJK 字体族,管不到它们 —— 包一层没用。
%======================================================================
\xeCJKDeclareCharClass{CJK}{"00D7} % × 乘号(占位符 ××× 最常用)
\xeCJKDeclareCharClass{CJK}{"2014} % — 破折号(em dash)
\xeCJKDeclareCharClass{CJK}{"25A1} % □ 白方框(勾选框 □ 同意 □ 不同意)
\xeCJKDeclareCharClass{CJK}{"25A0} % ■ 实心方框
\xeCJKDeclareCharClass{CJK}{"25CB} % ○ 白圆圈(单选题选项圈)
\xeCJKDeclareCharClass{CJK}{"25CF} % ● 实心圆
\xeCJKDeclareCharClass{CJK}{"2610} % ☐ 选票框
\xeCJKDeclareCharClass{CJK}{"2611} % ☑ 打勾选票框
\xeCJKDeclareCharClass{CJK}{"2612} % ☒ 打叉选票框
\xeCJKDeclareCharClass{CJK}{"221A} % √ 根号(勾选/判卷常用)
\xeCJKDeclareCharClass{CJK}{"203B} % ※ 参考标记
%======================================================================
% 五、行距
%
% 这里不全局改 \linespread,因为各模板需求不同(科技报告依赖 ctex
% 默认值,试卷归档封面/课程执行大纲/年度考核登记表必须归 1 才能
% 还原 docx 的精确行高)。只提供工具命令,由各模板自行调用。
%======================================================================
\newcommand{\ouclinespread}[1]{\linespread{#1}\relax}
\endinput