切换字体时要添加代码吗?

切换字体时要添加代码吗?

xeCJK包提供了一个键值选项xCJKecglue,用于设置在 CJK 脚本和拉丁脚本之间转换时的水平空间。此过渡空间通常为 15到 14 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 系列时错位会更加明显(当然数字宽度有很大不同)。


先前的尝试:我以前使用过一半的解决方案:不设置xCJKecgluexeCJK将插入一个正常拉丁空格默认情况下。所以原则上我可以\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}

CJ凯克胶

特别感谢Qing Lee (维护者xeCJK) 的建议everysel

相关内容