8

I find that inline fractions with the Stix Two fonts are a bit too tall, pushing the baselines apart. So I want to shrink them down a little. In principle, I know how; see below.

The problem is that the parameters get reset after a change in font size, even if the size change is local to a group. MWE:

\documentclass{minimal}
\usepackage{fontspec,unicode-math}
\setmathfont{STIX2Math.otf}
\begin{document}
  $\frac12$\quad
  \Umathfractionnumup\textstyle=5pt
  \Umathfractiondenomdown\textstyle=5pt
  $\frac12$\quad
  {\fontsize{8pt}{9pt}\selectfont$\frac12$}\quad
  $\frac12$
\end{document}

The output is as follows.

Output of lualatex run

The second fraction is what I wanted (more or less). But as you can see from the fourth one, parameters are back to standard after the smaller fraction has been typeset. So it seems that I need to hook into something to repeat the relevant settings somehow. I can set these parameters from lua as well, but I have been unable to find a suitable hook. In particular, setting this in luaotfload.patch_font does not cure the problem.

Yes, I could try to use \everymath, but that is prone to being overwritten by other stuff. Or maybe not. I'll try it if desperate, but it does not seem like a sufficiently robust solution.

Also, I wonder if this behaviour is the expected one? It does seem to make life difficult.

3
  • It occured to me that the simplest solution might be to patch \frac itself. But it seems inelegant. Aug 10 '17 at 13:12
  • patching the mathconstants table with patch_font should imho work. What did you try there? Aug 10 '17 at 14:49
  • @UlrikeFischer Thanks for the hint! I used it to find an answer, which I posted. Aug 10 '17 at 17:05
9

This seems to work:

\documentclass{minimal}
\usepackage{fontspec,unicode-math,luacode}
\begin{luacode}
  local patch_stix = function (fontdata)
    if fontdata.psname == "STIXTwoMath" then
      local mc=fontdata.MathConstants
      local mp=fontdata.mathparameters
      mc.FractionNumeratorShiftUp = 0.85 * mc.FractionNumeratorShiftUp
      mp.FractionNumeratorShiftUp = 0.85 * mp.FractionNumeratorShiftUp
      mc.FractionDenominatorShiftDown = 0.8 * mc.FractionDenominatorShiftDown
      mp.FractionDenominatorShiftDown = 0.8 * mp.FractionDenominatorShiftDown
    end
  end
  luatexbase.add_to_callback(
    "luaotfload.patch_font",patch_stix,
    "my_private_callbacks.patch_stix")
\end{luacode}
\setmathfont{STIX2Math.otf}
\begin{document}
  $\frac12$
\end{document}

It produces a fraction as follows:

A somewhat more compact fraction

How I found out:

After being gently prodded by Ulrike Fischer in a comment, I discovered luaotfload.pdf in the standard distribution. I ran the TeX code shown in Section 9.1 there, and looked at the structure of STIX2Math.otf. A little guesswork (wasn't that hard), I ended up with this solution. This answer was also tremendously helpful, of course.

Oddly, the fraction shifts are listed in both the MathhConstants section and the mathparamters section (with identical data), and you have to change both of them.

2
  • After the latest update of luaotfload I get the error 'directlua: attempt to index a nil value (local 'mc')' when running this. Anyone know a fix?
    – Michael
    Nov 13 '20 at 17:44
  • 1
    @Michael I have noticed the same thing. But I haven't had the time to try to figure out what happened, other than noting that the fontdata looks quite different now. I'll keep looking, but don't hold your breath. Nov 13 '20 at 20:22
2

2021 update

Improving on the answer of Harald Hanche-Olsen, I've updated the code slightly to work with a current TeXLive 2021 release of the STIX2Math font as well as the current lauaotfload library:

\documentclass{standalone}
\usepackage{fontspec,unicode-math,luacode}
\begin{luacode}
 local patch_stix = function (tfmdata)
  if tfmdata.psname == "STIXTwoMath" then
  
   -- Some of the loaded files do not appear to contain these MathConstants
   -- but I don't know why
   if not (tfmdata.MathConstants and next(tfmdata.MathConstants)) then 
    -- In those cases we simply do nothing
    return
   end
   
   local mc=tfmdata.MathConstants
   
   mc.FractionNumeratorShiftUp     = 0.85 * mc.FractionNumeratorShiftUp
   mc.FractionDenominatorShiftDown = 0.85 * mc.FractionDenominatorShiftDown
  end
 end
 
 luatexbase.add_to_callback(
  "luaotfload.patch_font",patch_stix,
  "my_private_callbacks.patch_stix")
\end{luacode}

\setmathfont{STIXTwoMath}

\begin{document}
    $\frac{a}{b}$
\end{document}

The central difference seems to be that the names have slightly changed. Maybe some more experiecend OTF expert could comment on why the font gets loaded multiple times (I still get that there are different variants), where sometimes the parameter is not available. But there is a very simply construct to catch these cases.

This is an example of how this looks without and with the patch applied:

Comparison of FractionNumeratorShift being

Background

Apart from the answer by Harald Hanche-Olsen I used this dumping script, which was taken from page 31 of the luaotfloat.pdf (version 2021-01-08 v3.17)

\begin{luacode}
 local dumpfile = "fontdump.lua"
 local dump_stix = function (fontdata)
  if fontdata.psname == "STIXTwoMath" then
   local data = table.serialize(fontdata)
   io.savedata(dumpfile, data)
  end
 end
 luatexbase.add_to_callback(
  "luaotfload.patch_font",dump_stix,
  "my_private_callbacks.dump_stix")
\end{luacode}

The resulting file can easily be read by a human to find the necessary parameters.

I also took inspiration from the luaotfload source code, more specifically this part.

1
  • Thank you for this update to my answer. I had noticed the problems with it, in the TL2020 version already I believe but hadn't had the time (nor the urgent need) to investigate further. I'll study your answer more closely, but decided it deserves an upvote already. Apr 4 at 7:23

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.