53

Question

How can I apply selective kerning within the numerator and denominator of an inline fraction? Specifically, I'd like to:

  • Tighten kerning after the numerator if it ends in 7
  • Loosen kerning after the numerator if it ends in 4
  • Tighten kerning before the denominator if it begins with 4
  • Loosen kerning before the denominator if it begins with 5 or 7

Background

I'm not quite satisfied with \sfrac or \nicefrac for typesetting fractions in passages of text, so I've been working on a macro called \textfrac. I'm pleased with the results so far, except the kerning, as mentioned above.

Features of \textfrac:

  • Uses 5-point type for numerator and denominator, rather than 7-point type.
  • In Computer Modern and Latin Modern, aligns perfectly with height and depth of standard numerals.
  • Works great inside of \textit and \textbf. (Except for small issue noted later.)
  • Takes an integer as an optional argument. If present, it adds micro-kerning between the integer and the fraction—for example 2½ becomes 2 ½. Also adds italic correction between the integer and the fraction.
  • Looks ahead using \futurelet to add additional a hair space after the fraction if it is not already followed by white space (for example a period or comma). The implementation of this isn't quite right yet, however, as it fails to detect the space token if the next token is } and then space.
  • A star version typesets the fraction using a horizontal bar instead of a diagonal solidus.

Here is a comparison with three popular fraction styles:

table

And the same comparison in paragraph form:

paragraphs

Additional question

How can I fix \textfrac* so that the denominator and horizontal bar are shifted to the left when used inside of \textsl and \textit?

rm sl it bf

Closer view:

want

Minimal working example

\documentclass{article}
\usepackage{ifthen}    % for use in \textfrac

\makeatletter

% Add a hair space if the fraction is followed by a non-space token.
\newcommand{\textfrac@kern}{%
  \ifx\textfrac@nexttoken\@sptoken%
    %
  \else%
    \kern.08333em%
  \fi%
}

% The non-star version of \textfrac uses a diagonal solidus.
\newcommand{\textfrac@nostar}[3][]{%
  \mbox{%
    \ifthenelse{\not\equal{#1}{}}%  Test for integer portion [optional #1]
      {#1\/\kern.05em}%                 Present? Emit integer and hair space
      {}%                             Not present? Emit nothing
    \raisebox{.775ex}{\tiny #2}%    Emit numerator [#2]
    \raisebox{.365ex}{\kern-.15em{\scriptsize /}\kern-.15em}%  Emit solidus
    \raisebox{0ex}{\tiny #3}%       Emit denominator [#3]
  }%
  \futurelet\textfrac@nexttoken\textfrac@kern%
}

% The star version of \textfrac uses a horizontal rule.
\newlength\textfrac@width@num%
\newlength\textfrac@width@denom%
\newlength\textfrac@width@%
\newcommand{\textfrac@star}[3][]{%
  \settowidth{\textfrac@width@num}{\tiny #2\/}%
  \settowidth{\textfrac@width@denom}{\tiny #3\/}%
  \ifthenelse{\lengthtest{\textfrac@width@num<\textfrac@width@denom}}%
    {\let\textfrac@width@\textfrac@width@denom}%
    {\let\textfrac@width@\textfrac@width@num}%
  \mbox{%
    \ifthenelse{\not\equal{#1}{}}%  Test for integer portion [optional #1]
      {#1\/\kern.08333em}%              Present? Emit integer and hair space
      {}%                             Not present? Emit nothing
    \ooalign{%
      \relax\cr%
      \noalign{\vskip-1.1ex}%
      {\hss\tiny #2\/\hss}\cr%        Emit numerator [#2]
      \noalign{\vskip1.1ex}%
      \rule[.6666ex]{\textfrac@width@}{.4pt}\cr%   Emit horizontal rule
      \noalign{\vskip.4ex}%
      {\hss\tiny #3\/\hss}\cr%        Emit denominator [#3]
      \noalign{\vskip-.4ex}%
    }%
  }%
  \let\textfrac@width\undefined%
  \futurelet\textfrac@nexttoken\textfrac@kern%
}

% Select between \textfrac and \textfrac*.
\def\textfrac{\@ifstar\textfrac@star\textfrac@nostar}

\makeatother

\begin{document}

\noindent\textrm{\textfrac[2]{1}{2} cups\quad \textfrac*[2]{1}{2} cups\\}
\noindent\textit{\textfrac[2]{1}{2} cups\quad \textfrac*[2]{1}{2} cups\\}

\end{document}
7
  • 7
    Very pretty! Much nicer than the others, I agree.
    – Ryan Reich
    Feb 1, 2012 at 22:47
  • 5
    @Todd Lehman: Definitely an improvement. Is this \textfrac going to be available in a package in the future? Feb 14, 2012 at 3:07
  • 2
    As soon as I learn how to do that, yeah. :) Feb 14, 2012 at 3:10
  • 2
    Hey @ToddLehman, have you "fixed" the \textfrac command yet? It looks fantastic and I would love to use it! I wouldn't even need a package, just the "fixed" macro would be amazing :) (fixed is in quotes since aside from a few minor things you pointed out, it's perfect!)
    – Alborz
    Jan 27, 2016 at 19:13
  • 2
    @Alborz — Oh boy. This was 4 years ago and I'm not sure, unfortunately. Looking at my final code, it looks like I've got corrections for sl and it modes by examining \f@shape, although I no longer understand how it works. The code says: \ifthenelse{\equal{\f@shape}{sl}}{\setlength\textfrac@intspace{.12em}}{} for sl and a parallel.15em for it. Then it's later got \ifthenelse{\equal{\f@shape}{sl}}{\setlength\textfrac@shift{.055em}}{} for sl, with .080em for it. Plus more tweaks. I have no idea anymore how it works. Would PM you the code if SX had PMing. Jan 27, 2016 at 21:59

2 Answers 2

18

One way to shift your numerators in an italic context would be

 {\hss\tiny\kern\fontdimen\@ne\font#2\/\kern-\fontdimen\@ne\font\hss}\cr%        Emit numerator [#2]

as for safe ways of looking ahead and adding space or not, you might want to look at latex's definition of \DeclareTextFontCommand which defines \textit and friends to add italic correction at the start or end, depending.

1
  • 4
    If you want to move the rule as well, perhaps easiest is to kern the denominator in the other direction to get the slant you want then perhaps kern before the entire oalign a bit to make up for the denominator being kerned in. Feb 1, 2012 at 22:57
1

This is my version using fontspec, for fonts like Cambria.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .