%====================================================================== % 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