Fandol 与 LuaTeX

Fandol 与 LuaTeX

的下一个版本babel将为 CJK 提供基本的换行功能luatex。当我进行一些实验时,我发现 Fandol 家族中存在一种奇怪且令人费解的行为。该文件为:

\documentclass{article}

\usepackage{fontspec}
\setmainfont{FandolSong-Regular.otf}

\begin{document}

\section{现代建筑教育}

中国的现代建筑教育体系不是来自本土建筑营造的延续

\end{document}

结果是:

FandolSong 和 LuaTeX 错误

请注意,章节主体紧跟标题,没有任何垂直分隔。它与xetex中的许多其他字体配合使用时效果良好luatex,但与 Fandol 配合使用时效果不佳。(TeXLive 2018 和 2019。)

答案1

这里发生了什么?让我们先看看\section实际做了什么:在 中article.cls\section定义为

    \newcommand\section{\@startsection {section}{1}{\z@}%
                                   {-3.5ex \@plus -1ex \@minus -.2ex}%
                                   {2.3ex \@plus.2ex}%
                                   {\normalfont\Large\bfseries}}

在 中source2e.pdf,我们可以找到 的所有参数的解释\@startsection。对于第五个参数,它表示

跳过后:如果为正,则跳至下方标题,否则为负,跳至进入标题的右侧。

您在 Fandol 中观察到的是标题与常规文本之间没有空格的标题,因此显然会触发第二种情况。但这意味着参数是不积极。这可能看起来很奇怪,因为上面的命令通过了{2.3ex \@plus.2ex},这当然看起来是积极的。

但是让我们退一步来看看{2.3ex \@plus.2ex}实际上是什么:\@plus...}与我们无关,所以我们只看2.3ex。这里的单位ex是当前字体的“x 高度”,但x-height对于像 Fandol 这样的 CJK 字体来说, a 没有意义。现在在相应的 OpenType 字段中,Fandol 必须设置一些值,因此 Fandol 将其“x 高度”设置为0。这由 luaotfload 拾取,它将 x 高度传递0给 LuaTeX。现在2.3ex=2.3*"x-height"=2.3*0=0

因此,afterskip参数设置为0,它不是正数。因此,根据其文档,\@startsection生成一个插入标题,在插入标题右侧不留任何空间。

现在 XeTeX 和 luaotfload 之间的区别在于缺少的 x 高度值的处理:

luaotfload 仅在字体不包含任何 x 高度时才使用 fallback,而 XeTeX 也会在字体明确指定 x 高度时使用 fallback 0。您可以通过修补字体在 LuaTeX 中模拟 XeTeX 行为:

\documentclass{article}
\directlua{
  luatexbase.add_to_callback("luaotfload.patch_font", function (fontdata)
    local parameters = fontdata.parameters
    if not parameters then return end
    if not (parameters.x_height or parameters[5] or 0) == 0 then return end
    if fontdata.characters and fontdata.characters[120] then
      parameters.x_height = fontdata.characters[120].height
    else
      parameters.x_height = (parameters.ascender or 0)/2
    end
  end, "Fix x-height")
}

\usepackage{fontspec}
\setmainfont{FandolSong-Regular.otf}

\begin{document}
\section{现代建筑教育}

中国的现代建筑教育体系不是来自本土建筑营造的延续

\end{document}

这确保了 x 高度(几乎)永远不会为零,因此\section可以再次起作用: 在此处输入图片描述

相关内容