这xeCJK
包提供了一个键值选项xCJKecglue
,用于设置在 CJK 脚本和拉丁脚本之间转换时的水平空间。此过渡空间通常为 1 ⁄ 5到 1 ⁄ 4 em。通常希望将其设置xCJKecglue + digit.width + xCJKecglue
为等于(方形)表意文字的宽度,以便像第一章
和第 1 章
(均表示“第 1 章”)这样的短语占用相同的空间。
与表意文字(通常设计成固定的正方形),拉丁字体通常成比例的。即使数字是表格/等距的,它们能在不同权重下具有不同的宽度(例如,粗体字样更宽)。我想\xeCJKsetup{ xCJKecglue = <glue> }
在面孔发生变化时自动添加(这涉及 4 个常见面孔两个都罗马家族和无家族)。基本上,我想知道是否xCJKecglue
可以以“面部感知”的方式指定。
\documentclass{article}
\usepackage{xeCJK} % loads fontspec internally
\setmainfont{TeX Gyre Schola} % Latin fonts specification
% Regular and italic faces have digit width 556/1000
\xeCJKsetup{ xCJKecglue = {\hskip 0.222em plus 0.05em minus 0.05em\relax} }
% Bold and bold italic faces have digit width 574/1000
%\xeCJKsetup{ xCJKecglue = {\hskip 0.213em plus 0.05em minus 0.05em\relax} }
\begin{document}
\huge
\begin{tabular}{ll}
第一章\rule[-0.2em]{0.4pt}{1em} & \bfseries 第一章\rule[-0.2em]{0.4pt}{1em} \\
第1章\rule[-0.2em]{0.4pt}{1em} & \bfseries 第1章\rule[-0.2em]{0.4pt}{1em} \\
\end{tabular}
\end{document}
注:以上 MWE 为最小因此很难观察到粗体字型的错位。切换到 sans 系列时错位会更加明显(当然数字宽度有很大不同)。
先前的尝试:我以前使用过一半的解决方案:不设置xCJKecglue
,xeCJK
将插入一个正常拉丁空格默认情况下。所以原则上我可以\fontdimen2
通过WordSpace
选项 进行修改fontspec
;也就是说,我可以做类似的事情
\setmainfont{TeX Gyre Schola}[
UprightFeatures={
WordSpace=...
},
BoldFeatures={
WordSpace=...
},
...
]
如果单词间空间没有扭曲,这种方法很好太多了(例如,当将 Source Han Sans 与 FiraGO 配对时,我会将单词间距缩小到 85%–98%)。但对于大多数其他配对,通常需要先放大拉丁字体,这会导致单词间距扭曲约 75% — 这无疑会破坏插入文档的拉丁短语/句子的颜色。
答案1
该解决方案由3部分组成。
第一的,检测当前正在使用哪种文本“模式”(正常、斜体、粗体等)?正如@AlanMunn(感谢!)指出的那样,提供了一种方法识别当前字体属性。一些嵌套条件可用于分别处理不同的字体。我将使用 XeTeX 原语\strcmp
执行字符串比较。逻辑测试的顺序应该是\f@family
,然后是,\f@series
最后是\f@shape
,不同数字宽度的概率依次递减。
\newcommand*\setCJKecglue{%
\ifnum\strcmp{\f@family}{\rmdefault}=0 %
% Code for the roman family
% \ifnum\strcmp{\f@series}{\mddefault}=0 %
% \ifnum\strcmp{\f@shape}{\updefault}=0 %
% % Code for roman regular
% \else
% % Code for roman italic
% \fi
% \else
% \ifnum\strcmp{\f@shape}{\updefault}=0 %
% % Code for roman bold
% \else
% % Code for roman bolditalic
% \fi
% \fi
\else
\ifnum\strcmp{\f@family}{\sfdefault}=0 %
% Code for the sans-serif family
\else
% Code for the mono-spaced family
\fi
\fi
}
第二,然后我们可以将嵌套条件添加到everysel
包。即\EverySelectfont{\setCJKecglue}
。
第三,虽然xeCJK
可以处理各种间距问题,但也有例外。其中一个例外是,像图~\ref{fig:example} 展示了
(意思是Figure~\ref{fig:example} shows that
)这样的短语最终会在参考编号周围留有正常的拉丁空格。应该改用图\nobreak\CJKecglue\ref{fig:example}\CJKecglue 展示了
。此外,当参考文献后面跟着标点符号(例如句号)时,应该使用图\nobreak\CJKecglue\ref{fig:example}。
(不带第二个\CJKecglue
)。
综合起来,我们有
\documentclass{article}
\usepackage{xeCJK} % loads fontspec internally
\setmainfont{TeX Gyre Schola}
\setsansfont{TeX Gyre Adventor}
\setmonofont{TeX Gyre Cursor}
\makeatletter
\def\setCJKecglue@nnn#1#2#3{%
\xeCJKsetup
{ xCJKecglue = {\hskip #1em plus #2em minus #3em\relax} }%
}
\newcommand*\setCJKecglue{%
\ifnum\strcmp{\f@family}{\rmdefault}=0 %
\ifnum\strcmp{\f@series}{\mddefault}=0 %
\ifnum\strcmp{\f@shape}{\updefault}=0 %
\setCJKecglue@nnn{0.09}{0.045}{0.03}%
\else
\setCJKecglue@nnn{0.5}{0.25}{0.167}%
\fi
\else
\ifnum\strcmp{\f@shape}{\updefault}=0 %
\setCJKecglue@nnn{1}{0.5}{0.333}%
\else
\setCJKecglue@nnn{1.5}{0.75}{0.5}%
\fi
\fi
\else
\ifnum\strcmp{\f@family}{\sfdefault}=0 %
\ifnum\strcmp{\f@series}{\mddefault}=0 %
\setCJKecglue@nnn{0.6}{0.3}{0.2}%
\else
\setCJKecglue@nnn{0.9}{0.45}{0.3}%
\fi
\else
\setCJKecglue@nnn{0.2}{0.1}{0.067}%
\fi
\fi
}
\makeatother
\usepackage{everysel}
\EverySelectfont{\setCJKecglue}
\newcommand\test{%
\begin{tabular}{llll}
第1章 & \itshape 第1章 & \bfseries 第1章 & \bfseries\itshape 第1章 \\
第 1 章 & \itshape 第 1 章 & \bfseries 第 1 章 & \bfseries\itshape 第 1 章 \\
\end{tabular}%
}
\newcommand*\figref[1]{%
图\nobreak\CJKecglue\ref{#1}\CJKecglue\ignorespaces
}
\newcommand*\figrefatend[1]{%
图\nobreak\CJKecglue\ref{#1}\ignorespaces
}
\begin{document}
\LARGE \test\par
\sffamily \test\par
\ttfamily \test\par
\rmfamily
\begin{figure}
\caption{A figure to be referenced.}\label{fig:example}
\end{figure}
Type ``1'': Figure~1 shows that\dots\par
图~1 展示了……(unbalanced spaces)\par
图\nobreak\CJKecglue1 展示了……(balanced spaces)\par
Use labels: Figure~\ref{fig:example} shows that\dots\par
图~\ref{fig:example} 展示了……(Latin spaces)\par
\figref{fig:example} 展示了……(correct spaces)\par
See Figure~\ref{fig:example}.\par
见\figref{fig:example}。(wrong space before full stop)\par
见 \figrefatend{fig:example} 。(no space before full stop)
\end{document}
特别感谢Qing Lee (维护者xeCJK
) 的建议everysel
。