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:
And the same comparison in paragraph form:
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
?
Closer view:
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}
\textfrac
going to be available in a package in the future?\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!)sl
andit
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}}{}
forsl
and a parallel.15em forit
. Then it's later got\ifthenelse{\equal{\f@shape}{sl}}{\setlength\textfrac@shift{.055em}}{}
forsl
, with .080em forit
. Plus more tweaks. I have no idea anymore how it works. Would PM you the code if SX had PMing.