7

The next release of babel will provide basic line breaking for CJK with luatex. When I was making some experiments I discovered an odd and puzzling behaviour in the Fandol family. The file is:

\documentclass{article}

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

\begin{document}

\section{现代建筑教育}

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

\end{document}

The result is:

Error with FandolSong and LuaTeX

Note the section body follows the title without any vertical break. It works as expected with xetex and with many other fonts in luatex, but not with Fandol. (TeXLive 2018 and 2019.)

7

What is going on here? Let's start by looking at what \section actually does: In article.cls, \section is defined by

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

In source2e.pdf, we can find an explenation of all the parameters of \@startsection. For the fifth, it says

afterskip: if positive, then skip to leave below heading, else negative of skip to leave to right of run-in heading.

What you observe with Fandol is a run-in heading with no space between heading and regular text, so obviously the second case is triggered. But this means that the parameter is not positive. This might appear odd, because the command above passes {2.3ex \@plus.2ex}, which certainly looks positive.

But let's take a step back and look what {2.3ex \@plus.2ex} actually is: The \@plus...} is not relevant for us, so we just look at 2.3ex. Here the unit ex is the "x-height" of the current font, but a x-height is not meaningful for a CJK-font like Fandol. Now in the corresponding OpenType field, Fandol has to set some value, so Fandol sets its "x-height" to 0. This is picked up by luaotfload, which passes the x-height 0 to LuaTeX. Now 2.3ex=2.3*"x-height"=2.3*0=0.

So the afterskip parameter is set to 0, which is not positive. So in conformance with it's documentation, \@startsection produces a run-in heading, leaving no space to right of run-in heading.

Now the difference between XeTeX and luaotfload is the handling of missing x-height values:

luaotfload only uses a fallback if the font does not contain any x-height, while XeTeX also uses the fallback if the font explicitly specifies a x-height of 0. You can emulate the XeTeX behaviour in LuaTeX by patching the font:

\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}

This ensures that the x-height is (almost) never zero, so \section works again: enter image description here

  • 2
    Ah you found the zero ex value too. I wonder we should add the patch generally. In latex ex is used quite often, so it is probably better if it is (almost) never 0. – Ulrike Fischer Apr 30 at 19:03
  • This can sometimes happen with non-CJK fonts. For example, I encountered it with Quattrocento, loaded via the quattrocento package. It does seem wise to exactly replicate pdflatex's behaviour here, since the effects of having an ex-height of zero can be quite perplexing. Actually I've no idea how I even found that this StackExchange answer was relevant; it was a stab in the dark! But the above Lua code does fix it. BTW this also happens for Quattrocento in XeLaTeX (where I obviously can't use the Lua workaround). – Daira Hopwood Jul 8 at 17:30
  • @DairaHopwood I don't know what you mean by "replicate pdflatex's behaviour", but at least the Lua code above will most likely be applied by default after the next luaotfload release. – Marcel Krüger Jul 8 at 17:40
  • Quattrocento is not a CJK font. But it has essentially the same issue with ex height being detected as zero, when loaded via the quattrocento package. (For all I know it's just a bug in that package.) – Daira Hopwood Jul 8 at 18:08
  • @DairaHopwood Oh, now I see what you meant. But at least on my system (up-to-date TeXLive 2019) I am unable to reproduce. Quattrocento has a non-zero "x-height", even if it is much smaller than the actual x-height of the font. – Marcel Krüger Jul 8 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.