Files
ouc_latex_template/科技报告/cls/font.cls
T
laoyang 5d59aa1853 科技报告字体调整:西文改 Cochineal、标题统一鸿蒙、代码换等宽 #19
用户反馈「标题一会儿黑体一会儿什么体的」。pymupdf 提取旧 PDF 定位到
三处字体分裂,逐条修掉。

一、西文从鸿蒙换成 Cochineal(cls/font.cls)

旧版 \setmainfont / \setsansfont / \setmonofont 三处全是鸿蒙。中文换成
思源宋体之后,正文就成了「中文衬线 + 西文无衬线」:同一行里英文数字比
汉字细、像陷进去,读起来割裂。

Cochineal 是 Minion 风格的衬线体(OFL 1.1,fonts/cochineal/ 已在库内),
与思源宋体灰度接近;度量与 Termes 只差 1.9%,不推着断行变。

\setsansfont 保持鸿蒙 —— 标题靠 \hm 切到 OUCHM 族,西文 sans 位仍是鸿蒙,
标题的中西文因此都是鸿蒙,与正文区分得开。

二、\hm 重定义为中西文一起切(cls/font.cls,本次核心)

这是「字体一会儿一个样」的真正来源。fonts.tex 里的 \hm 是
    \def\hm{\CJKfamily{OUCHM}}
纯 xeCJK 中文字族切换,管不到阿拉伯数字和拉丁字母。而标题、封面主标题、
摘要标题都用 \hm 表示「这是鸿蒙」,于是凡是标题里夹了西文就还是西文字体:

  · 章节编号 "1." "3.1" → 走 \setmainfont → 旧版是鸿蒙粗,改 Cochineal 后
    变成衬线粗,与中文鸿蒙粗并排
  · "这是一个很好用的 LaTex 模板" 里的 LaTex → 走 \setmainfont
  · 目录条目编号是数字、标题是中文 → 同一条目录两种字体

修法:本模板内把 \hm 重定义为 \hmlatin\CJKfamily{OUCHM},中西文一起切。
一次在源头解决,不在每个调用点补 \hmlatin —— 后者必然漏(封面、摘要、
目录标题、页眉、文本框标题各漏一次,本次实测漏了 4 处)。

不改 ../fonts.tex 的 \hm:幻灯片和简历也在用,它们没有这个问题,全局改
会外溢。

三、目录条目与页码归零(cls/title.cls)

\cftsecfont 等三条只管条目文字,页码走 \cft*pagefont,不显式清掉的话
目录里页码比标题还粗、最抢眼。两组共 6 条一起设 \normalfont。
不塞 \bfseries:加粗与否是各条目录自己的事,硬加会让二三级也变粗。

四、代码等宽位换 Latin Modern Mono(cls/font.cls)

旧版 \setmonofont 也是鸿蒙 —— 它不是等宽字体,代码里 i/l/1、m/w 宽度
不一,竖向对不齐、缩进看着是歪的。lmmono 是 TeX Live 自带,无需额外
字体文件。

⚠️ 这里不能用 Extension + UprightFont=*-regular:lm 系列文件名本身是
"lmmono10-regular.otf" 已带 -regular,再拼会变成 lmmono10-regular-regular
然后报 cannot be found。给完整文件名、不给 Extension。粗体用
lmmonolt10-bold(同族等宽,换粗体不错位),没有 lmmonobq 这个变体。

五、内容块保留 3 个 Underfull(cls/boxes.cls,只加注释不改代码)

第 208/214/220 行的 \verb|Illuminate\Foundation\Http\Kernel| 是 35 字符
不可断串,在内容块 371pt 内宽里塞不下。试过无效的:\emergencystretch
2em/10em(不是额度不够,是这行没有足够可拉伸 glue)、\sloppy(badness
从 1231 升到 3590,更差)。有效但不采用:\seqsplit(归零但任意字符处
断行,代码路径被切两段)、窄体 lmmonoltcond(归零但压缩可读性)。

结论:保留这 3 个,badness 1231 属轻微(10000 才是严重),渲染只是行末
留白略多。日志里看到它们属预期,不是回归。

六、report.tex 字体说明同步

第 52/58 行原文说「英文字体默认使用鸿蒙」,改后已不准确,重写为
Cochineal + Latin Modern Mono 的实际状况,并说明标题编号统一的原因。

验证(两套环境各跑两遍,逐字同数)

  WSL / TeX Live 2025:rc=0,error 0,Overfull 0,Underfull 4,10 页
  Windows / TeX Live 2022:rc=0,error 0,Overfull 0,Underfull 4,10 页

pymupdf 提取字体分布,两侧完全一致:
  Cochineal-Roman 782   OUCSerif-Regular 143   LMMono10-Regular 98
  OUCKai-Regular 33     HarmonyOS_Sans_SC_Bold 22   HarmonyOS_Sans_Bold 14
  OUCSerif-Bold 8       FontAwesome 5   HarmonyOS_Sans_SC 3
  ZhuqueFangsong 2      OUCSans-Regular 2   CMSY10 1   CMEX10 1
  HarmonyOS_Sans 1

标题逐页核对(中西文双档均属鸿蒙):
  p1 封面   HarmonyOS_Sans_SC_Bold「这是一个很好用的」+ HarmonyOS_Sans_Bold「LaTex」
  p2 目录   HarmonyOS_Sans_SC_Bold「目录」
  p5 摘要   HarmonyOS_Sans_SC_Bold + HarmonyOS_Sans_Bold「LaTex」
  p6 正文   HarmonyOS_Sans_Bold「1.」+ HarmonyOS_Sans_SC_Bold「准备工作」
  p10 正文  HarmonyOS_Sans_Bold「8.」+ HarmonyOS_Sans_SC_Bold「图标」

OUCSans-Regular 2 / ZhuqueFangsong-Regular 2 / HarmonyOS_Sans 1 三处少量
命中已逐个查清,都不是回归:
  · p6「黑体」「仿宋」—— 正文故意演示 \fzzdx / \fzfs 的示例文字
  · p8 每页同 bbox、45° 旋转、29.8pt —— 全页水印,设计如此
  · p10「HTTP/Console」—— 文本框标题走 fonttitle=\hm,改后已是
    HarmonyOS_Sans + HarmonyOS_Sans_SC,中西文都属鸿蒙

涉及文件:
  科技报告/cls/font.cls    默认族、\hm 重定义、等宽位
  科技报告/cls/title.cls   目录条目与页码归零
  科技报告/cls/boxes.cls   仅补 Underfull 记录注释,代码未改
  科技报告/report.tex      字体说明文字同步
2026-10-29 15:47:33 +08:00

193 lines
8.9 KiB
OpenEdge ABL
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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% fonts settings
%% 字体设定
%%
%% 【2026-11 改造记录:全部改为开源可商用字体】
%%
%% 旧版本这里用的是 5 个**方正商业字体** + 鸿蒙,字体文件都放在
%% 科技报告/font/ 下(共 92MB):
%% fangzhengshusong_GBK.TTF 方正书宋 SJK 正文
%% fangzhengxiaobiaosong_GBK.TTF 方正小标宋 粗体/标题
%% fangzhengkaiti_GBK.TTF 方正楷体 引文、页眉、题注
%% fangzhengfangsong_GBK.TTF 方正仿宋 斜体位
%% fangzhengzhongdengxian_GBK.TTF 方正中等线 等宽位
%%
%% 问题:方正这 5 款都**不允许随仓库分发**(个人非商用免费,商用须授权),
%% 把它们打进公开模板库属于越界使用;而且 92MB 的字体让 clone 变得很重。
%%
%% 现在全部映射到仓库公共字体包 ../fonts.tex(文件在 ../fonts/ 下):
%% 方正书宋 → OUC Serif(思源宋体 SC 子集,OFL 1.1)
%% 方正小标宋 → OUC Serif Bold(真粗体,思源宋体自带)
%% 方正楷体 → OUC Kai(霞鹜文楷子集,OFL 1.1)
%% 方正仿宋 → Zhuque Fangsong(朱雀仿宋,OFL 1.1)
%% 方正中等线 → OUC Sans(思源黑体 SC 子集,OFL 1.1)
%% 鸿蒙 → 保留 HarmonyOS Sans(华为官方允许免费商用)
%%
%% 上层的 \fzss / \fzxbs / \fzkai / \fzfs / \fzzdx / \hm 六个命令名
%% **保持不变**,所以 boxes.cls / code.cls / headandfoot.cls / cover.tex
%% 里的调用一行都不用改。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 开明式:句末点号用占一个汉字宽度,标号和句内点号占半个汉字宽度
%\punctstyle{kaiming}
%======================================================================
% 一、先载入仓库公共字体包
% 它负责:fontspec/xeCJK 的加载、\songti/\heiti/\kaiti/\fangsong/\tnr
% /\tnrb/\hm 的登记、以及 ×/□ 这类字符的 CJK 归类。
% 本文件只在其基础上覆盖"默认族",并补 5 个方正语义别名。
%======================================================================
\input{../fonts.tex}
%======================================================================
% 二、默认字体族
%
% 中文:OUC Serif 书宋(对应原方正书宋),粗体用 OUC Serif Bold
% (对应原方正小标宋 —— 小标宋本身就是宋体的标题变体)
% 西文:Cochineal(Minion 风格,OFL 1.1)
% 无衬线:鸿蒙 HarmonyOS Sans(标题、目录标题、封面标题都靠 \hm 切)
%
% ⚠️ Path= 是相对**编译时工作目录**(= 科技报告/)的,不是相对 cls/。
% 故写作 ../fonts/...,不要写 ../../。
%
% ⚠️⚠️ 西文为什么从 HarmonyOS 换成 Cochineal(2026-10 改,#19)
%
% 旧版这里 \setmainfont / \setsansfont / \setmonofont 三处全是鸿蒙。
% 中文换成思源宋体之后,正文就成了「中文衬线 + 西文无衬线」,
% 同一行里英文数字明显比汉字细、比汉字"陷进去",读起来割裂。
%
% 更明显的副作用在目录:\setmainfont 是西文字体总开关,目录条目的
% 编号("1." 是数字)走它 → 鸿蒙粗体;而条目标题是中文 → 走
% \setCJKmainfont → 思源宋体粗。**同一条目录里两种字体**,
% 这就是"标题一会儿黑体一会儿什么体"的实际来源。
%
% 换成 Cochineal 后:中文宋体、西文衬线,灰度接近;目录编号与标题
% 也归到同一字族。度量与 Termes 只差 1.9%,不推着断行变。
%
% ⚠️ \setsansfont 保持鸿蒙 —— 标题用 \hm(CJK 族名 OUCHM)切换,
% 西文 sans 位仍是鸿蒙,标题的中西文因此都是鸿蒙,与正文区分得开。
%======================================================================
\setmainfont{cochineal}[
Extension = .otf,
Path = ../fonts/cochineal/,
UprightFont = *-Roman,
BoldFont = *-Bold,
ItalicFont = *-Italic,
BoldItalicFont = *-BoldItalic,
]
\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,
]
% 等宽位:真等宽,供代码块(listings 的 \ttfamily)使用。
% 旧版这里也是鸿蒙 —— 它不是等宽字体,代码里 i/l/1、m/w 宽度不一,
% 竖向对不齐,缩进看起来是歪的。
% lmmono(Latin Modern Mono)是 TeX Live 自带,无需额外字体文件。
%
% ⚠️ 这里**不能**用 Extension + UprightFont=*-regular 的组合。
% lm 系列的文件名本身就是 "lmmono10-regular.otf",已经带 -regular 后缀;
% 再配 Extension=.otf 加 *-regular,fontspec 会拼成
% lmmono10-regular-regular.otf
% 然后报 The font "lmmono10-regular-regular" cannot be found。
% 正确做法是给完整文件名、不给 Extension。
% ⚠️ 没有 lmmonobq 这个变体;粗体用 lmmonolt10-bold(同属 lmmono 家族,
% 字宽与 regular 一致,换粗体不会让代码错位)。
\setmonofont{lmmono10-regular.otf}[
ItalicFont = lmmono10-italic.otf,
BoldFont = lmmonolt10-bold.otf,
]
% \hm 已在 fonts.tex 里登记(CJK 族名 OUCHM),这里不重复定义。
% 只把 CJK 的 sans / mono 两族指到鸿蒙上,与旧版行为一致。
\setCJKsansfont{HarmonyOS_Sans_SC_Regular.ttf}[
Path = ../fonts/harmonyos-sans/,
BoldFont = HarmonyOS_Sans_SC_Bold.ttf,
]
\setCJKmonofont{OUCSans}[
Extension = .otf,
Path = ../fonts/ouc-sans/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]
\XeTeXlinebreaklocale "zh"
\XeTeXlinebreakskip = 0pt plus 1pt
%======================================================================
% 二之二、重定义 \hm:中文与西文一起切到鸿蒙(#19)
%
% 问题:fonts.tex 里的 \hm 是 \def\hm{\CJKfamily{OUCHM}} —— 这只是
% xeCJK 的**中文字族**切换,管不到阿拉伯数字和拉丁字母。而本模板的
% 标题、封面主标题、摘要标题都用 \hm 来做"这是鸿蒙",于是凡是标题里
% 夹了西文("LaTex"、编号 "1." "3.1")就还是渲染成西文字体,
% 表现为同一个标题里中文鸿蒙、西文衬线 —— 就是"字体一会一个样"。
%
% 解法:在本模板内把 \hm 重定义为「中文字族 + 拉丁字族」一起切。
% \hmlatin 由 fonts.tex 用 \newfontfamily 定义,是 Latin 字族命令,
% 与 \CJKfamily 作用域不同,可以并存。
%
% ⚠️ 必须是 \renewcommand,不能 \newcommand —— 名字已被 fonts.tex 定义。
% ⚠️ 只改本模板,不动 ../fonts.tex:幻灯片和简历也在用那个 \hm,
% 全局改会让它们跟着变,而它们没有这个"标题里混西文"的问题。
% 这是本模板的局部修正,不该外溢。
% ⚠️ 重定义要在所有 \hm 调用**之前**。本文件由 report.cls 在
% \begin{document} 前 \input,位置没问题;不要把这段挪到后面。
%======================================================================
\renewcommand{\hm}{\hmlatin\CJKfamily{OUCHM}}
%======================================================================
% 三、5 个方正语义别名
%
% 用 \setCJKfamilyfont + \def 而非 \newCJKfontfamily,理由见 fonts.tex:
% 后者是 LaTeX3 的 \NewDocumentCommand,命令已存在时会报错中断。
% 命令名照旧,调用点零改动。
%======================================================================
% 书宋(原方正书宋)—— 正文
\setCJKfamilyfont{fzss}[
Extension = .otf,
Path = ../fonts/ouc-serif/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCSerif}
\newcommand{\fzss}{\CJKfamily{fzss}}
% 小标宋(原方正小标宋)—— 标题/强调,用宋体真粗体
\setCJKfamilyfont{fzxbs}[
Extension = .otf,
Path = ../fonts/ouc-serif/,
UprightFont = *-Bold,
BoldFont = *-Bold,
]{OUCSerif}
\newcommand{\fzxbs}{\CJKfamily{fzxbs}}
% 楷体(原方正楷体)—— 引文、页眉、题注
\setCJKfamilyfont{fzkai}[
Extension = .ttf,
Path = ../fonts/ouc-kai/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCKai}
\newcommand{\fzkai}{\CJKfamily{fzkai}}
% 仿宋(原方正仿宋)—— 斜体位
% ⚠️ 朱雀仿宋只有常规一档。旧版这里配的是"方正仿宋",也是常规字面,
% 所以观感一致;但若在 \fzfs 下用 \bfseries,不会真的变粗。
\setCJKfamilyfont{fzfs}[
Extension = .ttf,
Path = ../fonts/zhuque-fangsong/,
UprightFont = *-Regular,
]{ZhuqueFangsong}
\newcommand{\fzfs}{\CJKfamily{fzfs}}
% 中等线(原方正中等线)—— 等宽位,用思源黑体
\setCJKfamilyfont{fzzdx}[
Extension = .otf,
Path = ../fonts/ouc-sans/,
UprightFont = *-Regular,
BoldFont = *-Bold,
]{OUCSans}
\newcommand{\fzzdx}{\CJKfamily{fzzdx}}