ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LaTeX中文字体粗体警告解析:SimSun加粗失败与解决方案

LaTeX中文字体粗体警告解析:SimSun加粗失败与解决方案 1. 这个警告到底在说什么1.1 警告出现的典型场景如果你用北航论文模板写过毕业设计大概率见过这么一条黄色警告LaTeX Font Warning: Font shape TU/SimSun(1)/b/n undefined (font) using TU/SimSun(1)/m/n instead on input line 123.我第一次看到的时候第一反应是“完了字体坏了”。后来发现论文还能正常编译PDF也能出只是某些地方的中文没有变成粗体。今天就把这个警告的来龙去脉一次说清楚顺便给出一套能直接用在我北航模板上的解决方案。先说结论这个警告不致命但它说明一个实际问题——你写的中文粗体没有真正生效。在Word里点个B就加粗在XeLaTeX里却要多绕好几个弯。北航模板本身是基于ctexbook文档类搭建的底层走的是XeLaTeX加fontspec的中文字体方案。正文的默认中文字体是SimSun也就是宋体。问题恰恰出在宋体身上。1.2 逐字拆解警告内容的含义这条警告看似天书拆开看每一个字段都有明确含义。Font shape TU/SimSun(1)/b/n undefined这是LaTeX字体选择机制NFSSNew Font Selection Scheme在报错。它按“编码/字体族/字重/字形”四元组来描述一种字体状态TU字体编码表示Unicode字体XeLaTeX下的西文和CJK字体都走这个编码。SimSun(1)字体族名称(1)是fontspec在内部为同一字体不同feature设置生成的实例编号。简单理解宋体被加载了不止一份配置其中一份内部编号叫SimSun(1)。bbold粗体字重。nnormal常规字形相对斜体而言。后面紧接着(font) using TU/SimSun(1)/m/n instead意思就是当前字体族里没有粗体变体我只好拿常规字重来顶替。m代表medium即常规字重。所以最终效果就是你想加粗但实际显示的是普通宋体。触发警告的本质很简单XeLaTeX在编译到某个中文粗体命令时去找SimSun(1)的b字重没找到于是回退到m字重。模拟宋体有没有粗体还真没有。2. 为什么北航论文模板会触发这个警告2.1 模板基于ctexbook的字体策略北航论文模板BUAAThesis目前主流的版本基本沿用了ctexbook文档类。ctex宏包对中文字体做了标准化配置默认情况下它会把中文字体分为中文罗马字体CJKrmfamily默认映射到宋体。中文无衬线字体CJKsffamily默认映射到黑体。中文等宽字体CJKttfamily默认映射到仿宋或楷体。正文里的\textrm、\textsf、\texttt等命令都会映射到对应字体族。而\bfseries、\textbf这类西文粗体命令对中文字体也会生效但生效范围和字体是否有粗体变体直接相关。北航模板里很多地方会直接用\bfseries或者\textbf去做标题强调比如章节标题图表标题里的“图1-1”、“表1-1”摘要里的关键词引导词正文里需要强调的术语这些命令在西文里很安全因为Times New Roman、Arial这些字体都有真正的粗体字重。但中文宋体没有。2.2 中文字体为什么普遍没有“粗体”这是一个被问过无数遍的问题为什么Word里宋体可以加粗XeLaTeX里就不行先说结论中易宋体SimSun这个字体文件本身只携带了Regular一种字重没有Bold。Word里你选中宋体点“B”本质上是系统做了伪粗体渲染——把字形横向拉伸加粗也叫Faux Bold。这个效果是Word帮你在显示层面处理的并没有改变字体文件本身。XeLaTeX不一样。它按照字体文件真实包含的字重去匹配b对应Bold字重m对应Regular。SimSun没有Bold所以匹配失败。这跟“字体不支持”是一回事不是LaTeX坏了而是它太较真。再补充一个细节Windows自带的宋体叫SimSun但它的字体族内部还包含一个NSimSun新宋体同样只有常规字重。中易黑体SimHei也只有一个字重。真正带Bold字重的常见中文字体一般是方正、汉仪这类商业字体或者思源宋体这种开源字体思源宋体甚至从ExtraLight到Heavy带了七个字重。所以模板默认配置下中文粗体缺失是很正常的事不是你环境配错了。2.3 触发点定位哪些地方会调用粗体中文要知道具体是哪一行触发最直接的办法是看警告末尾的on input line 123。这个行号指的是当时正在处理的.tex文件行号。我踩坑时发现触发点主要集中在下面这几个位置\chapter{...}里的中文章节标题如果模板对章节标题加了\bfseries处理必然触发。\textbf{中文内容}直接写在正文里。表格里用\textbf加粗表头中文。图表的caption里用了\textbf{图1-1}这种写法。北航模板里还有一类隐蔽触发点模板自定义的标题格式宏。有些版本会在\makechapterhead这类内部命令里手动设置字体属性比如加一个\bfseries。这类情况很难靠直接搜索正文找到必须去.cls或.sty文件里搜。定位方法我可以先用\tracingfonts1打开字体追踪但实际操作中最简单的是二分注释法先把正文分成几大块注释掉一半编译一次看到警告是否还在就能快速缩小范围。3. 解决方案让粗体真正显示出来核心思路只有两条一是在字体配置层面给宋体补一个“粗体”二是从使用层面避免对中文用不存在的粗体。下面三个方案都能解决但适用场景不一样。3.1 方案一给宋体开启伪粗体AutoFakeBold这是最省事、最暴力的方案在导言区加几行配置\usepackage{fontspec} \setCJKmainfont[AutoFakeBold{2.5}]{SimSun}AutoFakeBold后面的参数是伪粗体拉伸程度2.5是比较稳妥的经验值。数字越大加粗效果越明显但也越容易让笔画糊在一起。默认值其实是AutoFakeBoldtrue效果大约是2.0偏弱中文小字号下基本看不太出来。如果你使用的是ctex文档类也可以直接给ctex传参\documentclass[fontsetwindows]{ctexbook} \setCJKmainfont[AutoFakeBold{2.5}]{SimSun}放在\begin{document}之前就能生效。伪粗体的原理是渲染阶段把字形做横向加粗处理。它没有改变字体文件只是让XeLaTeX在输出PDF时“画”出更粗的字形。好处是代码改动最小坏处是粗体观感跟真正的粗体有差距尤其字号超过三号之后伪粗体的边缘会有轻微的“发虚”感。3.2 方案二把中文粗体映射到黑体推荐这个方案属于“曲线救国”但效果反而是最接近Word排版习惯的。原理很简单既然宋体没有粗体那我们在配置文件里告诉LaTeX——当需要中文粗体时直接用黑体替换。\usepackage{fontspec} \setCJKmainfont[ BoldFont{SimHei} ]{SimSun}这个配置的意思是正文默认用宋体遇到\bfseries或\textbf时不再找“宋体的粗体”而是换用黑体。为什么说它最接近Word排版习惯因为中文排版里“加粗强调”的传统等价物本来就是黑体。古籍和公文排版里重要文字用黑体或宋体加粗但宋体加粗实际上是近代铅字排版里才出现的替代方案。用黑体作为粗体映射视觉层次清楚也不会出现伪粗体的毛边问题。对于北航模板来说还有一个额外好处论文标题如果用黑体加粗反而更能体现“标题层级”的区分感。如果你还想顺手解决斜体问题可以一起配置\setCJKmainfont[ BoldFont{SimHei}, ItalicFont{KaiTi}, BoldItalicFont{SimHei} ]{SimSun}斜体映射到楷体这在中文排版的传统做法里也算常见。不过北航模板对斜体要求不多可以根据实际需要选择。3.3 方案三从源头避免对中文使用\bfseries这个方案最适合“不想动全局配置、只想改局部表现”的场景。核心思路是对中文强调不要用西文粗体命令改用中文字体切换命令。比如正文里原本是\textbf{注意这里的结论需要重点理解}改成{\heiti 注意这里的结论需要重点理解}黑体本身就是中文字体族的一个成员\heiti在ctex里直接可用指向中易黑体。这样切换字体而不是“加粗”显示效果稳定也不触发任何字体警告。对于摘要里的关键词我习惯这样处理\noindent\textbf{关键词}LaTeXXeLaTeX字体配置可以改成\noindent{\heiti 关键词}LaTeXXeLaTeX字体配置如果模板里某些章节标题内部用了\bfseries在正文层面不好改那就只能去.cls文件里找或者用方案一/二从字体层面兜底。3.4 三种方案的对比与取舍方案改动量效果风险AutoFakeBold伪粗体极小几行配置有加粗观感边缘略虚字号大时效果一般粗体映射到黑体极小几行配置清晰、稳定符合中文排版习惯粗体字重统一变成黑体无法保留宋体笔画风格避免使用\bfseries中等需逐个修改最可控按需切换工作量大模板内部命令难处理我个人优先推荐方案二。它代码简单、效果稳定、可批量复现而且不影响英文粗体。方案一适合“只想让警告消失”的临时场景。方案三适合论文正文里偶尔一两处强调的精细化处理。4. 实操记录修改北航模板的完整过程4.1 确认模板版本和文件结构不同版本的北航模板配置位置不一样。动手之前先确认你用的是哪一套旧版基于ctexbook主文件通常是main.tex配置直接写在导言区。新版基于biblatex扩展的版本通常会拆出doctor.cls、master.cls这类文档类文件也会在main.tex里保留导言区。有些早期版本还用GBK编码配合CCT那就不是XeLaTeX能直接处理的建议直接换新模板。我以最常见的Github仓库BUAAThesis为例。下载解压后典型的文件布局是BUAAThesis/ ├── main.tex ├── data/ │ ├── chapter01.tex │ ├── chapter02.tex │ └── ... ├── figures/ ├── bst/ 或 bib/参考文献样式 ├── master.cls └── doctor.cls我一般用master.cls写硕士论文。里面的字体配置可能在main.tex也可能被封装进.cls。先全局搜一下grep -n setCJKmainfont\|setCJKfamilyfont\|ctexset master.cls main.tex就能定位到所有和CJK字体相关的配置行。4.2 修改导言区的具体代码假设你的模板用的是ctexbook文档类且正文已经引入了fontspec。推荐在main.tex导言区加上这一段% 解决中文字体粗体缺失问题粗体映射到黑体 \setCJKmainfont[ BoldFont{SimHei} ]{SimSun} % 如果标题需要一个更明显的粗体效果可以用下面这组 \setCJKmainfont[ AutoFakeBold{2.5}, BoldFont{SimHei} ]{SimSun}注意同时设置AutoFakeBold和BoldFont时BoldFont优先级更高。也就是说系统会优先使用SimHei作为粗体只有找不到SimHei时才退到伪粗体。如果模板里还单独定义了\songti、\heiti这些中文字体命令它们内部的字体族映射不一定跟随\setCJKmainfont变化。此时需要单独加\setCJKfamilyfont{zhsong}[ BoldFont{SimHei} ]{SimSun} \setCJKfamilyfont{zhhei}[ BoldFont{SimHei} ]{SimHei}zhsong是ctex内部用来映射宋体的family名称。这样设置之后\songti、\zihao这些命令内部调用宋体时遇到粗体也会自动替换成黑体。如果是新版模板main.tex里可能已经存在\setCJKmainfont{SimSun}或\ctexset{fontsetfandol}前者的意思是使用系统里的SimSun后者是使用fandol开源字体。这两种情况都适用上面的配置但要注意如果fontset是fandol那你系统里未必有SimSun和SimHei而fandol字体集里的宋体其实也是不带粗体的。这时候最简单的方法是把fontset改成\ctexset{fontsetnone} \setCJKmainfont[ BoldFont{SimHei} ]{SimSun}fontsetnone是让ctex不自动配置中文字体全部由我们自己手动指定。这样做的控制力最强也最容易排查问题。4.3 编译验证与效果检查配置改完之后重新用XeLaTeX编译xelatex main.tex如果模板还有参考文献可能需要跑完整的编译链xelatex main.tex bibtex main xelatex main.tex xelatex main.tex编译日志里如果还有字体警告说明有些字体是在.cls文件里单独定义的。此时打开日志文件搜索关键词grep -n Font Warning main.log逐条检查警告的family字段比如Font shape TU/SimSun(1)/b/n undefined Font shape TU/SimSun(0)/b/n undefined如果SimSun(0)和SimSun(1)都在报错说明模板在不止一处加载了宋体配置。最简单的处理是直接在.cls文件里搜索setCJK把重复配置统一改成带BoldFont的版本。验证效果时我习惯在正文写一个对比段\noindent 普通宋体。\\ \textbf{加粗宋体理想情况下应显示为黑体效果。}\\ {\heiti 直接切换黑体作为对照组。}编译后用PDF阅读器放大到200%看第二行是否和第三行视觉上一致。如果一致说明粗体映射成功如果第二行还是普通宋体说明字体配置没被正确加载。有的PDF阅读器会自己渲染伪粗体造成“看起来加粗了”的错觉。所以最严谨的检查方法是用Adobe Acrobat打开点击文字选中看字体属性里写的字体名。第二行的字体应该是SimHei而不是SimSun-Regular。这个细节可以区分“真替换”还是“阅读器帮忙显示”。5. 常见问题与排查技巧实录5.1 为什么同样配置在别的机器上正常这个现象很典型。你在一台电脑上编译警告消失了换一台电脑警告又出现了。原因多半是系统里没有对应字体。方案二要求系统装有SimHei。Windows系统一般自带但macOS和Linux默认没有。macOS上常见的宋体是“宋体-简”或STSong黑体是“黑体-简”或STHeiti。如果你在macOS上写北航模板可以改成\setCJKmainfont[ BoldFont{STHeiti} ]{STSong}不过更省心的做法是统一用思源系列\setCJKmainfont[ BoldFont{Source Han Serif SC SemiBold} ]{Source Han Serif SC Regular}配置字体之前一定要先确认系统识别的字体名称。可以用fc-list查Linux/macOSWindows上则直接看字体文件属性fc-list | grep -i SimHei fc-list | grep -i Source HanmacOS也可以用fc-list :langzh如果发现字体名和你写的不一致哪怕只是多了一个空格XeLaTeX都会直接报错或者静默回退。5.2 改了之后英文粗体也变了怎么办我的第一版配置曾经踩过这个坑。当时为了省事直接在导言区写了\setmainfont[ BoldFont{SimHei} ]{SimSun}注意这里用的是\setmainfont它影响的是西文字体。结果编译出来的PDF里英文粗体全变成了黑体里的西文字形观感很奇怪。而且正文英文字母都变成了SimSun的西文部分和Times New Roman的风格差很多。正确做法是中文字体用\setCJKmainfont西文字体保持模板默认。如果模板默认没有设置西文字体再单独指定\setmainfont{Times New Roman} \setCJKmainfont[ BoldFont{SimHei} ]{SimSun}这样英文走Times New Roman的粗体中文走宋体黑体替换互不干扰。5.3 警告不在报错却在怎么定位具体行有时候警告信息里带的行号是宏包内部的行号不是正文里的行号。这种情况在\chapter这种复杂命令里特别常见因为实际内容是在.cls文件的某个内部命令里排版的。定位技巧分三步第一步打开main.log找到警告出现的完整段落。第二步从警告提示的行号往前找最近的\section或\chapter标题判断大概位置。第三步如果还是定位不到就在正文里用二分法注释把后半部分全部注释掉编译如果警告消失说明问题出在后半部分然后再把后半部分对半切重复操作。这个方法比较笨但准。我有一次花了一个小时定位一个隐蔽警告最后发现是模板的abstract环境里自动加了\bfseries跟我正文一点关系都没有。遇到这种情况就别折腾正文了回到方案二整体映射粗体才是正路。5.4 常见问题速查表现象原因解决办法Font shape TU/SimSun(1)/b/n undefined宋体无粗体字重配置BoldFont映射到黑体警告消失但粗体没效果PDF阅读器自动渲染伪粗体干扰判断查看PDF文字属性确认实际字体macOS上SimHei不存在系统字体名不同改用STHeiti或思源黑体英文粗体也变成黑体风格误用了\setmainfont改用\setCJKmainfont配置中文字体同一套配置一台机器正常一台报错系统字体缺失用fc-list核对字体名修改导言区后警告仍在.cls内部仍有一份字体配置搜索.cls里的setCJK统一修改使用fontsetfandol仍报错fandol宋体同样无粗体设置fontsetnone并手动指定字体用AutoFakeBold后加粗过度拉伸系数过大系数调整到2~3之间测试还有一类常见但容易被忽略的情况字体文件被特殊命名。有的同学自己装了“宋体加粗”这种名义上的字体文件但实际它的内部字重名不是Bold。XeLaTeX认的是字体内部元数据不认文件名。这时候可以用\newCJKfontfamily手动注册\newCJKfontfamily\songbiaofamily[ UprightFont* Regular, BoldFont* Bold ]{YourFontName}这个方法相对冷门但遇到字体命名不规范时很管用。6. 关于伪粗体和真粗体的一条实操心得最后再分享一条我在实际使用中的体会。网上很多帖子会把“警告”说得非常可怕一上来就让你重装字体、换编译器。但字体警告在LaTeX里属于非常常见的一类信息只要编译能通过PDF能生成它就不是阻断性错误。不过也别因为“不致命”就完全无视。粗体失效在论文里是本质问题——章节标题、强调词和正文混在一起读者很难快速抓住重点。北航研究生院对论文格式有明确要求不少专业要求“标题黑体”、“正文宋体”。在这种要求下把中文粗体正确映射到黑体其实不是“绕过警告”而是更符合中文排版规范的做法。我自己现在维护的论文模板里已经默认加入\setCJKmainfont[ BoldFont{SimHei} ]{SimSun}这句话带来的PDF效果和Word里“宋体加粗”的视觉效果基本一致。偶尔遇到需要更细的加粗控制时我再单独定义\setCJKmainfont[ AutoFakeBold{1.8}, BoldFont{SimHei} ]{SimSun}AutoFakeBold设为1.8是在SimHei不可用时的兜底方案不会影响正常路径。如果你用的是新版本的北航模板记得把逻辑放到main.tex导言区的最末尾避免被.cls文件里的默认配置覆盖。如果模板更新过务必备份一份自己的配置片段这样升级模板时不用重新调字体。这套配置我前后用了多个项目从硕士论文到期刊模板都验证过只要字体装对了基本不会再碰见Font shape undefined的警告。
返回列表