Files
ouc_latex_template/幻灯片/theme/beamerfontthemeOUCSlide.sty
T
laoyang 8aa979739a 字体统一:建公共字体目录,全部改用开源可商用字体 (#6)
七个模板原先分两套做法:幻灯片/fonts(49MB 鸿蒙 18 个字重)与
科技报告/font(92MB,含 5 款方正商业字体),其余模板直接调系统
SimSun/SimHei/KaiTi/FangSong/Times New Roman。换机器就编不出来,
方正系列也不允许随仓库分发。

统一到仓库根的 fonts/ + fonts.tex:
- OUC Serif(思源宋体 SC 子集)   —— 宋体
- OUC Sans(思源黑体 SC 子集)    —— 黑体
- OUC Kai(霞鹜文楷子集)          —— 楷体
- Zhuque Fangsong(朱雀仿宋)      —— 仿宋
- TeX Gyre Termes                  —— 西文 Times 等价(度量逐字相同)
- HarmonyOS Sans                   —— 幻灯片/科技报告原有字体

fonts.tex 是唯一允许声明字体的地方,7 个模板全部 \input 它。
字体体积 141MB -> 49MB(去掉重复),全库共用一套最小集合。

几处踩过的坑(均已写进源码注释):
- \newCJKfontfamily 与 ctex 默认 fontset 冲突会中断编译,改用
  \setCJKfamilyfont + \def
- \newfontfamily 缺粗体档会让 \bfseries 静默失效,四档必须全给
- UprightFont= 与主参数不能同时给,否则文件名被拼两次
- Path= 相对编译时工作目录,不是相对 .sty
- ×/□/○ 等符号按 Unicode 区段被判成西文,需 \xeCJKDeclareCharClass
- 中文斜体的 ItalicFont 与主字体不在同一目录,须在 ItalicFeatures
  里单独写 Path/Extension(否则报 OUCKai-Regular cannot be found)

顺带:
- 科技报告 report.tex 的字体演示正文改为新字体名(原文写着方正系列)
- 试卷归档封面新模板并入本库
- 科技报告 shell 命令框底色改海大蓝(#5 遗留)

验证(7 个模板 8 个 PDF 全量重编 + 逐行 A/B 对照):
- 错误 0,缺字 0
- 幻灯片 362 行逐行完全一致,零漂移
- 年度考核登记表 / 劳务发放说明表 / 试卷题型示例 / 参考答案 文本完全一致
- 课程执行大纲 仅 2 处断字连字符差异(throughout、processing),
  1 条 6.39pt Overfull 已论证不可见(距纸张右边缘仍有 20.7mm)
- 科技报告 内嵌字体方正归零,只剩 OUC Serif/Sans/Kai + Zhuque
- 全库正文 857 个非 ASCII 字符,四款中文字体(含粗体)覆盖 100%
2026-10-27 00:43:14 +08:00

267 lines
11 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.
%!TEX program = xelatex
%% 版本:1.0
%% 作者:杨永全
%% 本文件的主要作用,是定义各种元素的字体
%% 完成日期:2022-05-09
\usepackage[UTF8]{ctex}
%\usepackage{xeCJK}
%字体
%======================================================================
% 字体全部取自仓库公共字体包 ../../fonts.tex(文件在 ../../fonts/ 下)。
%
% 旧版这里是 Path=fonts/ 直接读本目录下的 幻灯片/fonts/ —— 那 18 个
% 鸿蒙字体文件共 49MB,与其它模板重复,且一旦别处升级就会版本不一致。
% 现在统一到仓库根的 fonts/,全库只有一份。
%
% ⚠️ 路径用 ../fonts/ 而不是 ../../fonts/:
% 本文件虽然在 幻灯片/theme/ 下,但被 \usetheme 载入时,
% XeTeX 解析 Path= 的相对基准是**编译时的工作目录**(= 幻灯片/),
% 不是本文件所在目录。用 ../../ 会跑到仓库外面去找。
% 同理 \input{../fonts.tex} 也是相对工作目录的。
%======================================================================
\input{../fonts.tex}
% 幻灯片的主字体是鸿蒙:西文用 HarmonyOS Sans,中文用 HarmonyOS Sans SC。
% 公共包已把它们登记为 \hmlatin(西文)与 \hm(CJK),这里把三个
% fontspec 的"默认族"都指过去 —— beamer 的 \sffamily / \ttfamily
% 都要落到鸿蒙上,否则正文会出现一半鸿蒙、一半 Termes 的混排。
\setmainfont{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,
]
\setsansfont{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,
]
\setmonofont{HarmonyOS_Sans_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
]
%设置中文字体 鸿蒙字体
\setCJKmainfont{HarmonyOS_Sans_SC_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
BoldFont = HarmonyOS_Sans_SC_Bold.ttf,
ItalicFont = HarmonyOS_Sans_SC_Regular.ttf,
BoldItalicFont = HarmonyOS_Sans_SC_Bold.ttf,
]
\setCJKsansfont{HarmonyOS_Sans_SC_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
BoldFont = HarmonyOS_Sans_SC_Bold.ttf,
ItalicFont = HarmonyOS_Sans_SC_Regular.ttf,
BoldItalicFont = HarmonyOS_Sans_SC_Bold.ttf,
]
\setCJKmonofont{HarmonyOS_Sans_SC_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
]
%以下为原模板代码,未做改动
\mode<presentation>
\setbeamerfont{sectiontitle}{size*={18pt}{20pt},series=\bfseries} % section标题字体大小
\setbeamerfont{title}{size*={15pt}{16pt},series=\bfseries} % 标题字体大小
\setbeamerfont{subtitle short}{size*={11pt}{12pt},series=\mdseries} % 副标题 短的 字体大小
\setbeamerfont{subtitle long}{size*={9pt}{9pt},series=\mdseries} % 副标题 长的 字体大小
\setbeamerfont*{subtitle}{parent=subtitle long} % 使用父标题
\setbeamerfont*{subtitle}{parent=subtitle short} % 使用父标题
%\setbeamerfont{normal text}{size*={8pt}{9pt}} % 14pt, baselineskip 18pt
\setbeamerfont{footline}{size*={6pt}{7pt}} %页脚文字大小
%\setbeamerfont{frametitle}{size*={16pt}{16pt},series=\bfseries} %30pt, baselineskip 36pt
\setbeamerfont{framesubtitle}{size*={10pt}{11pt},series=\mdseries} % 普通页面,副标题的字体大小
% 特殊文本域的字体设置
\setbeamerfont{caption}{size=\small}
\setbeamerfont{caption name}{parent={structure,caption}}
\setbeamerfont{date}{size*={10pt}{10pt}}
\setbeamerfont{footline}{parent={tiny structure}}
\setbeamerfont{headline}{parent={tiny structure}}
\setbeamerfont{institute}{size=\footnotesize, series=\itshape}
\setbeamerfont{navigation symbols}{size*={7pt}{8pt}}
\setbeamerfont{section in toc}{parent=structure}
\setbeamerfont{section in toc shaded}{parent=section in toc}
% 列表
\setbeamerfont{item}{parent=structure}
\setbeamerfont{subitem}{parent=item}
\setbeamerfont{subsubitem}{parent=subitem}
\setbeamerfont{item projected}{size=\tiny, parent={item, projected text}}
\setbeamerfont{subitem projected}{parent=item projected}
\setbeamerfont{subsubitem projected}{parent=subitem projected}
\setbeamerfont{description item}{parent=item}
\setbeamerfont{enumerate item}{parent=item}
\setbeamerfont{enumerate subitem}{parent=subitem}
\setbeamerfont{enumerate subsubitem}{parent=subsubitem}
\setbeamerfont{itemize/enumerate body}{}
\setbeamerfont{itemize/enumerate subbody}{size=\small}
\setbeamerfont{itemize/enumerate subsubbody}{size=\footnotesize}
\setbeamerfont{itemize item}{parent=item}
\setbeamerfont{itemize subitem}{parent=subitem}
\setbeamerfont{itemize subsubitem}{parent=subsubitem}
\makeatletter
%% 字母间距
\providecommand{\emptydummyb}[1]{} % eats argument of \uppercase() and and \addfontfeature{}
\providecommand{\emptydummya}[2][]{#2}{} % eats optional argument of textls and forwards #2 argument
\providecommand{\addfontfeature}[1]{} % defined only if latex or pdflatex is used
\providecommand{\textls}[2][]{#2}{} % defined only if microtype is loaded
%% \MakeTextUppercase 原本由 textcase 宏包提供,但本模板并未加载该宏包,
%% 导致 title/subtitle/part/frametitle 的 allcaps 选项报 Undefined control sequence。
%% 这里在未定义时退回到 LaTeX 内核的 \MakeUppercase(新版内核语义与 textcase 一致)。
\@ifundefined{MakeTextUppercase}{\let\MakeTextUppercase\MakeUppercase}{}
% 定义的一些其他命令
\def\beameroucslide@titleformat#1{#1}
\def\beameroucslide@subtitleformat#1{#1}
\def\beameroucslide@partformat#1{#1}
\def\beameroucslide@frametitleformat#1{#1}
%% 标题文字定义
\pgfkeys{
/beameroucslide/font/title/.cd,
.is choice,
.default=regular,
regular/.code={%
\let\beameroucslide@titleformatcaps\emptydummya%
\let\beameroucslide@titleformatspacinga\emptydummya%
\let\beameroucslide@titleformatspacingb\emptydummyb%
},
allcaps/.code={%
\let\beameroucslide@titleformatcaps\MakeTextUppercase%
\let\beameroucslide@titleformatspacinga\emptydummya%
\let\beameroucslide@titleformatspacingb\emptydummyb%
},
}
%% 副标题文字定义
\pgfkeys{
/beameroucslide/font/subtitle/.cd,
.is choice,
.default=allcaps,
regular/.code={%
\let\beameroucslide@subtitleformatcaps\emptydummya%
\let\beameroucslide@subtitleformatspacinga\emptydummya%
\let\beameroucslide@subtitleformatspacingb\emptydummyb%
\setbeamerfont{subtitle long}{size*={9pt}{11pt},series=\bfseries} % 18pt, baselineskip 22pt
},
allcaps/.code={%
\let\beameroucslide@subtitleformatcaps\MakeTextUppercase%
\let\beameroucslide@subtitleformatspacinga\emptydummya%
\let\beameroucslide@subtitleformatspacingb\emptydummyb%
\setbeamerfont{title}{size*={16pt}{16pt},series=\bfseries} % 30pt, baselineskip 36pt%
},
}
%% 普通页面文字设置
\pgfkeys{
/beameroucslide/font/frametitle/.cd,
.is choice,
.default=allcaps,
regular/.code={%
\let\beameroucslide@frametitleformatcaps\emptydummya%
\let\beameroucslide@frametitleformatspacinga\emptydummya%
\let\beameroucslide@frametitleformatspacingb\emptydummyb%
\setbeamerfont{frametitle}{size*={14pt}{18pt},series=\bfseries} % 32pt, baselineskip 36pt%
},
allcaps/.code={%
\let\beameroucslide@frametitleformatcaps\MakeTextUppercase%
\let\beameroucslide@frametitleformatspacinga\emptydummya%
\let\beameroucslide@frametitleformatspacingb\emptydummyb%
\setbeamerfont{frametitle}{size*={14pt}{18pt},series=\bfseries} % 32pt, baselineskip 36pt%
},
}
%% 段落文字设置
\pgfkeys{
/beameroucslide/font/part/.cd,
.is choice,
.default=allcaps,
regular/.code={%
\let\beameroucslide@partformatcaps\emptydummya%
\let\beameroucslide@partformatspacinga\emptydummya%
\let\beameroucslide@partformatspacingb\emptydummyb%
\setbeamerfont{part}{size*={16pt}{18pt},series=\bfseries} % 30pt, baselineskip 36pt%
},
allcaps/.code={%
\let\beameroucslide@partformatcaps\MakeTextUppercase%
\let\beameroucslide@partformatspacinga\emptydummya%
\let\beameroucslide@partformatspacingb\emptydummyb%
\setbeamerfont{part}{size*={16pt}{18pt},series=\bfseries} % 30pt, baselineskip 36pt%
},
}
% redefine beamer title, subtitle, part and frametitle command
\patchcmd{\beamer@title}%
{\def\inserttitle{#2}}%
{\protected\def\inserttitle{{\beameroucslide@titleformatspacingb{LetterSpace=15.0}\beameroucslide@titleformatcaps{\beameroucslide@titleformatspacinga[120]{#2}}}}}%
{}%
{\PackageError{beameroucslide}{Patching original title failed}\@ehc}
\patchcmd{\beamer@subtitle}%
{\def\insertsubtitle{#2}}%
{\protected\def\insertsubtitle{{\beameroucslide@subtitleformatspacingb{LetterSpace=15.0}\beameroucslide@subtitleformatcaps{\beameroucslide@subtitleformatspacinga[120]{#2}}}}}%
{}%
{\PackageError{beameroucslide}{Patching original subtitle failed}\@ehc}
\patchcmd{\beamer@part}%
{\def\insertpart{\expandafter\hyperlink\partlink}}%
{\def\insertpart{{\beameroucslide@partformatspacingb{LetterSpace=15.0}\beameroucslide@partformatcaps{\beameroucslide@partformatspacinga[120]{\expandafter\hyperlink\partlink}}}}}%
{}%
{\PackageError{beameroucslide}{Patching original part failed}\@ehc}
% beamer 3.69(TeX Live 2023)起 \beamer@@frametitle 的定义发生了变化:
% 用 \beamer@insertframetitlecontinuation 取代了 \usebeamertemplate*{frametitle continuation}。
% 因此这里按 beamer 版本分别处理,保证在 TeX Live 2022 与 2023 下都能编译通过。
% 注意:判断必须写在文件顶层(不能把 \patchcmd 嵌进 \@ifundefined 等宏的参数里),
% 否则 \patchcmd 的搜索串会被改写而导致补丁失败。
\ifcsname beamer@insertframetitlecontinuation\endcsname
% 新版 beamer(TeX Live 2023 及以后):按新定义重写,并加入标题格式控制
\long\def\beamer@@frametitle[#1]#2{%
\ifblank{#2}{}{%
\gdef\insertframetitle{{\beameroucslide@frametitleformatcaps{#2}%
\ifnum\beamer@autobreakcount>0\relax{}\space%
\beamer@insertframetitlecontinuation\fi}}%
\gdef\beamer@frametitle{#2}%
\gdef\beamer@shortframetitle{#1}%
}%
}%
\else
% 旧版 beamer(TeX Live 2022 及以前):沿用原有的补丁方式
\patchcmd{\beamer@@frametitle}
{{%
\gdef\insertframetitle{{#2\ifnum\beamer@autobreakcount>0\relax{}\space%
\usebeamertemplate*{frametitle continuation}\fi}}%
\gdef\beamer@frametitle{#2}%
\gdef\beamer@shortframetitle{#1}%
}}
{{%
\gdef\insertframetitle{{\beameroucslide@frametitleformatcaps{#2}\ifnum%
\beamer@autobreakcount>0\relax{}\space%
\usebeamertemplate*{frametitle continuation}\fi}}%
\gdef\beamer@frametitle{#2}%
\gdef\beamer@shortframetitle{#1}%
}}
{}
{\PackageError{beameroucslide}{Patching original frame title failed}\@ehc}%
\fi
\makeatother