Files

386 lines
18 KiB
TeX
Raw Permalink Normal View History

%======================================================================
% 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 小型大写,行为正确。
%
%
% 1) SmallCapsFont 这个选项**与本文件上面的 ItalicFeatures /
% 只有 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}}
2026-11-01 09:29:00 +08:00
% 西文:显式取 Times 形态
%
% ⚠️ 四个档位必须全给。只给 UprightFont 的话,在 \bfseries 环境里会落到
% "Font shape `TU/texgyretermes/b/n' undefined" 并静默替换,
2026-11-01 09:29:00 +08:00
% 表现为加粗失效(试卷的 \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 才能
2026-11-01 09:29:00 +08:00
% 还的精确行高)。只提供工具命令,由各模板自行调用。
%======================================================================
\newcommand{\ouclinespread}[1]{\linespread{#1}\relax}
\endinput