[Tex/LaTex] Less vertical space in frac

luatexmath-modeunicode-math

I'm using unicode-math in lualatex with the Cambria Math fonts. Compared to Computer Modern math, there is too much vertical space between fractions. Is there a way I can achieve my adjustment without having to patch \frac? For example a fontspec or unicode-math option?

i.e. I'm looking for an option to change the vertical space around the fraction bar.

Edit: added xfrac case and +frac, +numr/+dnom.

+frac just +sups all digits. Custom xfrac only works in math mode when enclosing the arguments in \text{19} but not with \text{#1}?!.

LuaTeX-0.70.2, Cambria 5.96

\documentclass{article}
\usepackage{fontspec}
\usepackage{xfrac}
\usepackage{unicode-math}
\setmathfont{Cambria Math}
\setmainfont{Cambria}

\newcommand{\otfrac}[2]{%
    \frac%
        {\raisebox{-.1em}{\scriptsize $#1$}}%
        {\raisebox{.15em}{\scriptsize $#2$}}%
}

\newcommand{\ofrac}[2]{%
    \text{%
        {\addfontfeature{VerticalPosition=Numerator}#1}%
        \divslash{}%
        {\addfontfeature{VerticalPosition=Denominator}#2}
    }%
}

\begin{document}
% tfracs look weird:
\noindent here is a first ygygyg line of text\\
bit too large: $\frac{19}{30}$. $\otfrac{19}{30}$ better?\\
here is anothÁÁÁÁÁÁ line of text\\[.5em]
%
% default sfrac looks weirder:
default sfrac text \sfrac{19}{30} math $\sfrac{19}{30}$\\
%
% customising helps some:
\DeclareInstance{xfrac}{default}{text}{
    numerator-top-sep = -.1ex,
    denominator-bot-sep = -.1ex,
    slash-symbol=\divslash,
}
\DeclareCollectionInstance{plainmath}{xfrac}{mathdefault}{math}{
    numerator-top-sep = -.2ex,
    denominator-bot-sep = -.1ex,
    scale-factor = 0.8333,
    scale-relative = true,
    slash-right-mkern = -0mu,
    slash-left-mkern = -0mu,
    slash-symbol=\text{\divslash}
}
\UseCollection{xfrac}{plainmath}
custom sfrac text \sfrac{19}{30} math $\sfrac{19}{30}$\\
%
% +frac feature just superscripts all digits
{\addfontfeature{Fractions=On} +frac 19/30, bad: 24. }
+numr/+dnom: \ofrac{19}{30} \\
%
% customize sfrac this way:
\DeclareInstance{xfrac}{default}{text}{
    numerator-bot-sep = 0pt, denominator-bot-sep = 0pt,
    scaling = false, slash-symbol=\divslash,
    numerator-format={\addfontfeature{VerticalPosition=Numerator}#1},
    denominator-format={\addfontfeature{VerticalPosition=Denominator}#1},
}
\ExplSyntaxOn
\DeclareCollectionInstance{plainmath}{xfrac}{mathdefault}{math}{
    numerator-top-sep = \c_max_dim, numerator-bot-sep = 0pt,
    denominator-bot-sep = 0pt, scaling = false,
    slash-right-mkern = 0mu, slash-left-mkern = 0mu,
    slash-symbol=\text{\divslash},
    %------------------vvvv-- or no \text{}, doesn't matter.
    numerator-format={\text{\addfontfeature{VerticalPosition=Numerator}#1}},
    denominator-format={\text{\addfontfeature{VerticalPosition=Denominator}#1}},
}
\ExplSyntaxOff
\UseCollection{xfrac}{plainmath}
% nice
otf custom sfrac text \sfrac{19}{30}
% what?!
math $\sfrac{19}{30}, \sfrac{\text{19}}{\text{30}}$\\

\end{document}

rendering of code sample


I'm not using \sfrac with anything other than digits as arguments anyway so I'll use this instead for consistency, but a way to modify \tfrac would still be interesting, or is \tfrac = \otfrac the best way?

Best Answer

The positioning of numerators and denominators is controlled by a font parameter that can easily be modified in LuaLaTeX:

\documentclass[pagesize=auto, version=last]{scrartcl}
\usepackage{fontspec}
\usepackage{unicode-math}
\usepackage{luacode}
\usepackage{luatexbase-mcb}
\setmathfont{Cambria Math}
\setmainfont{Cambria}
\begin{luacode*}
  local function patch_cambria_frac(fontdata)
    if fontdata.psname == "CambriaMath" then
      local mc = fontdata.MathConstants
      mc.FractionNumeratorShiftUp = 0.4 * mc.FractionNumeratorShiftUp
      mc.FractionDenominatorShiftDown = 0.4 * mc.FractionDenominatorShiftDown
    end
  end
  luatexbase.add_to_callback("luaotfload.patch_font", patch_cambria_frac, "cambria_frac")
\end{luacode*}
\begin{document}
$\frac{19}{30}$
\end{document}
Related Question