https://github.com/latex3/latex2e
Tip revision: a3972890dd3e71080a333ad867b3ddd2f93de48f authored by Joseph Wright on 21 November 2023, 20:45:24 UTC
Step release tag
Step release tag
Tip revision: a397289
ltfssaxes.dtx
% \iffalse meta-comment
%
% Copyright (C) 2019-2023
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
% -------------------------------------------
%
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
% https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This file has the LPPL maintenance status "maintained".
%
% The list of all files belonging to the LaTeX base distribution is
% given in the file `manifest.txt'. See also `legal.txt' for additional
% information.
%
% The list of derived (unpacked) files belonging to the distribution
% and covered by LPPL is defined by the unpacking scripts (with
% extension .ins) which are part of the distribution.
%
% \fi
% \iffalse
%%% From File: ltfssaxes.dtx
%% Copyright (C) 1999-2020 Frank Mittelbach
%
%<*driver>
% \fi
%
%
\ProvidesFile{ltfssaxes.dtx}
[2023/10/30 v1.0i LaTeX Kernel (NFSS Axes handing)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
\DocInput{ltfssaxes.dtx}
\end{document}
%</driver>
% \fi
%
%
%
%
% \GetFileInfo{ltfssaxes.dtx}
% \title{A new font selection scheme for \TeX{} macro packages\\
% (Axes Handling)\thanks
% {This file has version number
% \fileversion\ dated \filedate}}
%
% \author{Frank Mittelbach}
%
% \MaintainedByLaTeXTeam{latex}
% \maketitle
%
% This file contains the implementation for handling extra axes
% splitting the series and the values into sub-categories. selection
% commands. See other parts of the \LaTeX\ distribution, or \emph{The
% \LaTeX\ Companion} for higher level documentation of the
% \LaTeX\ Font Selection Scheme.
%
%
%
% \MaybeStop{}
%
% \changes{v1.0h}{2020/12/04}{Reorganized the rollback data}
%
% Everything in the this file got introduced 2020/02/02, so we use large rollback
% chunks, only interrupted if necessary.
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\DeclareFontSeriesChangeRule}{Series change rules}%
% \end{macrocode}
%
%
%
% \section{Changing the font series}
%
% In the original NFSS implementation the series was a single
% attribute stored in \cs{f@series} and so one always had to specify
% both weight and width together. This means it was impossible to
% typeset, a paragraph in a condensed font and inside have a few words
% in bold weight (but still condensed) without doing this manually by
% requesting \verb=\fontseries{bc}\selectfont=.
%
% The new implementation now works differently by looking both at the
% current value of \cs{f@series} and the requested new series and out
% of that combination selects a resulting series value. Thus, if the
% current series is \texttt{c} and we ask for \texttt{b} we now get
% \texttt{bc}.
%
% This is done by consulting a simple lookup table. This table is
% configurable (though most likely that flexibility will seldom of
% ever be needed) Adding or changing entries in this table are done
% with \cs{DeclareFontSeriesChangeRule}.
%
% \subsection{The series lookup table}
%
%
% \begin{macro}{\DeclareFontSeriesChangeRule}
% The \cs{DeclareFontSeriesChangeRule} defines entries in a simple
% database (implemented as a set of commands) that define mappings
% between from an existing series and requested new series and maps
% that to a result series (and additionally offers an alternative
% if the desired one is not existing):
% \begin{itemize}
% \item[\texttt{\#1}] current \cs{f@series}
% \item[\texttt{\#2}] requested new series
% \item[\texttt{\#3}] result (if that exist for the given font family
% \item[\texttt{\#4}] alternative result (if \texttt{\#3} does not exist)
% \end{itemize}
% If an \texttt{.fd} file has its own substitution rules then
% \texttt{\#3} exist and thus \texttt{\#4} is not applied.
%
% If there is no matching database entry or if neither the result
% nor the alternate result exist in the font family the requested
% new series is used (which then may trigger substitutions later on.
% \begin{macrocode}
\def\DeclareFontSeriesChangeRule#1#2#3#4{%
\@namedef{series@#1@#2}{{#3}{#4}}}
% \end{macrocode}
% \end{macro}
%
% \subsection{Mapping rules for series changes}
%
% The rules set up use explicit series values not \cs{..default}
% indirections; my current feeling is that this is in fact better.
%
% With 9 weights and 9 width classes this table is getting a bit large
% in the end (324 entries) but on the other hand it doesn't change and
% accessing speed and it is fast this way.
%
% We could alternatively split the axis and maintain weight and width
% separately, but that would take more processing time and would not
% allow for setting up explicit exceptions nicely (not sure that this
% would ever get used though).
%
% Design considerations for mapping entries:
% \begin{itemize}
% \item
%
% We make \texttt{m} to reset both weight and width (as this is
% how it always worked). To reset just the width \texttt{?m} is
% provided and to reset just the weight \texttt{m?}.
%
% \item
%
% We do support ``\texttt{m}\textit{width}'' and
% ``\textit{weight}\texttt{m}'', e.g., \texttt{mec} to mean ``go to
% medium weight and extra-condensed width''. At the end of the
% process we automatically drop any leftover \texttt{m} in the
% series name (unless it is just a single \texttt{m}).
%
%
% \item
%
% If there is no table entry then the target series is used
% unconditionally. This means that any request to set both weight
% and width (e.g. \texttt{bx} or \texttt{ulc}) needs no table
% entries.
% For that reason there are no entries which have a weight+width as
% request (i.e., second argument).
%
% In particular this is also true for cases involving \texttt{m},
% e.g., \texttt{bm} (bold medium width) which automatically gets
% reduced result in \texttt{b} or \texttt{mc} (medium weight
% condensed) which becomes \texttt{c} as a result.
%
% \item
%
% Only a few entries have ``alternative'' values and perhaps most of
% them should get dropped. Or maybe not \ldots{} needs some thought
% perhaps.
%
% The idea is that you don't want the normal substitution to kick
% in because that would reset the shape first and it may be better
% to stay with \texttt{b} when a change to \texttt{c} is requested
% and \texttt{bc} doesn't exist, than to go to first change the
% shape to \texttt{n} and then find that \texttt{bc/n} doesn't
% exist either and thus ending up with \texttt{m/n}.
%
% \item
%
% Also: while I did set up all nine standard weight values from
% \texttt{ul} to \texttt{ub} I only bothered to provide entries for
% \texttt{ec}, \texttt{sc}, \texttt{c} and \texttt{x}, because other levels of
% compression/expansion are not in any real fonts that I know.
%
% Could and perhaps should be eventually extended to cover the
% whole set.
%
% \end{itemize}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {bc}{b}{bc}{}
\DeclareFontSeriesChangeRule {bc}{c}{bc}{}
\DeclareFontSeriesChangeRule {bc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {bc}{ec}{bec} {bc}
\DeclareFontSeriesChangeRule {bc}{el}{elc}{}
\DeclareFontSeriesChangeRule {bc}{l}{lc}{}
\DeclareFontSeriesChangeRule {bc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {bc}{sc}{bsc} {bc}
\DeclareFontSeriesChangeRule {bc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {bc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {bc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {bc}{x}{bx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {bx}{b}{bx}{}
\DeclareFontSeriesChangeRule {bx}{c} {bc} {bx} %<-----
\DeclareFontSeriesChangeRule {bx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {bx}{ec} {bec} {bx} %<-----
\DeclareFontSeriesChangeRule {bx}{el}{elx}{}
\DeclareFontSeriesChangeRule {bx}{l}{lx}{}
\DeclareFontSeriesChangeRule {bx}{sb} {sbx} {}
\DeclareFontSeriesChangeRule {bx}{sc} {bsc} {bx} %<-----
\DeclareFontSeriesChangeRule {bx}{sl}{slx} {}
\DeclareFontSeriesChangeRule {bx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {bx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {bx}{x}{bx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {b}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {b}{c} {bc} {b} %<-----
\DeclareFontSeriesChangeRule {b}{ec} {bec} {b} %<-----
\DeclareFontSeriesChangeRule {b}{sb} {sb} {b} %<-----
\DeclareFontSeriesChangeRule {b}{sc} {bsc} {b} %<-----
\DeclareFontSeriesChangeRule {b}{x} {bx} {b} %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {c}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {c}{b}{bc}{}
\DeclareFontSeriesChangeRule {c}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {c}{el}{elc}{}
\DeclareFontSeriesChangeRule {c}{l}{lc}{}
\DeclareFontSeriesChangeRule {c}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {c}{sl}{slc}{}
\DeclareFontSeriesChangeRule {c}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {c}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {c}{x}{x}{m} %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ebc}{b}{bc}{}
\DeclareFontSeriesChangeRule {ebc}{c}{ebc}{}
\DeclareFontSeriesChangeRule {ebc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {ebc}{ec}{ebec}{ebc}
\DeclareFontSeriesChangeRule {ebc}{el}{elc}{}
\DeclareFontSeriesChangeRule {ebc}{l}{lc}{}
\DeclareFontSeriesChangeRule {ebc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {ebc}{sc}{ebsc}{ebc}
\DeclareFontSeriesChangeRule {ebc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {ebc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {ebc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {ebc}{x}{ebx}{}
% \end{macrocode}
%
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ec}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {ec}{b}{bec}{}
\DeclareFontSeriesChangeRule {ec}{eb}{ebec}{}
\DeclareFontSeriesChangeRule {ec}{el}{elec}{}
\DeclareFontSeriesChangeRule {ec}{l}{lec}{}
\DeclareFontSeriesChangeRule {ec}{sb}{sbec}{}
\DeclareFontSeriesChangeRule {ec}{sl}{slec}{}
\DeclareFontSeriesChangeRule {ec}{ub}{ubec}{}
\DeclareFontSeriesChangeRule {ec}{ul}{ulec}{}
\DeclareFontSeriesChangeRule {ec}{x}{x}{m} %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {sc}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {sc}{b}{bsc}{}
\DeclareFontSeriesChangeRule {sc}{eb}{ebsc}{}
\DeclareFontSeriesChangeRule {sc}{el}{elsc}{}
\DeclareFontSeriesChangeRule {sc}{l}{lsc}{}
\DeclareFontSeriesChangeRule {sc}{sb}{sbsc}{}
\DeclareFontSeriesChangeRule {sc}{sl}{slsc}{}
\DeclareFontSeriesChangeRule {sc}{ub}{ubsc}{}
\DeclareFontSeriesChangeRule {sc}{ul}{ulsc}{}
\DeclareFontSeriesChangeRule {sc}{x}{x}{m} %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ebx}{b}{bx}{}
\DeclareFontSeriesChangeRule {ebx}{c}{ebc}{}
\DeclareFontSeriesChangeRule {ebx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {ebx}{ec}{ebec}{}
\DeclareFontSeriesChangeRule {ebx}{el}{elx}{}
\DeclareFontSeriesChangeRule {ebx}{l}{lx}{}
\DeclareFontSeriesChangeRule {ebx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {ebx}{sc}{ebsc}{}
\DeclareFontSeriesChangeRule {ebx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {ebx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {ebx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {ebx}{x}{ebx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {eb}{c}{ebc}{}
\DeclareFontSeriesChangeRule {eb}{ec}{ebec}{}
\DeclareFontSeriesChangeRule {eb}{sc}{ebsc}{}
\DeclareFontSeriesChangeRule {eb}{x}{ebx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {elc}{b}{bc}{}
\DeclareFontSeriesChangeRule {elc}{c}{elc}{}
\DeclareFontSeriesChangeRule {elc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {elc}{ec}{elec}{}
\DeclareFontSeriesChangeRule {elc}{el}{elc}{}
\DeclareFontSeriesChangeRule {elc}{l}{lc}{}
\DeclareFontSeriesChangeRule {elc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {elc}{sc}{elsc}{}
\DeclareFontSeriesChangeRule {elc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {elc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {elc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {elc}{x}{elx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {elx}{b}{bx}{}
\DeclareFontSeriesChangeRule {elx}{c}{elc}{}
\DeclareFontSeriesChangeRule {elx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {elx}{ec}{elec}{}
\DeclareFontSeriesChangeRule {elx}{el}{elx}{}
\DeclareFontSeriesChangeRule {elx}{l}{lx}{}
\DeclareFontSeriesChangeRule {elx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {elx}{sc}{elsc}{}
\DeclareFontSeriesChangeRule {elx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {elx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {elx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {elx}{x}{elx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {el}{c}{elc}{}
\DeclareFontSeriesChangeRule {el}{ec}{elec}{}
\DeclareFontSeriesChangeRule {el}{sc}{elsc}{}
\DeclareFontSeriesChangeRule {el}{x}{elx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {lc}{b}{bc}{}
\DeclareFontSeriesChangeRule {lc}{c}{lc}{}
\DeclareFontSeriesChangeRule {lc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {lc}{ec}{lec}{}
\DeclareFontSeriesChangeRule {lc}{el}{elc}{}
\DeclareFontSeriesChangeRule {lc}{l}{lc}{}
\DeclareFontSeriesChangeRule {lc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {lc}{sc}{lsc}{}
\DeclareFontSeriesChangeRule {lc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {lc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {lc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {lc}{x}{lx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {lx}{b}{bx}{}
\DeclareFontSeriesChangeRule {lx}{c}{lc}{}
\DeclareFontSeriesChangeRule {lx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {lx}{ec}{lec}{}
\DeclareFontSeriesChangeRule {lx}{el}{elx}{}
\DeclareFontSeriesChangeRule {lx}{l}{lx}{}
\DeclareFontSeriesChangeRule {lx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {lx}{sc}{lsc}{}
\DeclareFontSeriesChangeRule {lx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {lx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {lx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {lx}{x}{lx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {l}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {l}{b} {b} {bx} %<-----
\DeclareFontSeriesChangeRule {l}{c} {lc} {l} % ? %<-----
\DeclareFontSeriesChangeRule {l}{ec} {lec} {l} % ? %<-----
\DeclareFontSeriesChangeRule {l}{sb} {sb} {b} % ? %<-----
\DeclareFontSeriesChangeRule {l}{sc} {lsc} {l} % ? %<-----
\DeclareFontSeriesChangeRule {l}{x} {lx} {l} % ? %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {m}{bx} {bx} {b} %<-----
\DeclareFontSeriesChangeRule {m}{b} {b} {bx} %<-----
\DeclareFontSeriesChangeRule {m}{c} {c} {m} %<-----
\DeclareFontSeriesChangeRule {m}{ec} {ec} {m} %<-----
\DeclareFontSeriesChangeRule {m}{l} {l} {m} %<-----
\DeclareFontSeriesChangeRule {m}{sb} {sb} {b} %<-----
\DeclareFontSeriesChangeRule {m}{sc} {sc} {m} %<-----
\DeclareFontSeriesChangeRule {m}{x} {x} {m} %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {sbc}{b}{bc}{}
\DeclareFontSeriesChangeRule {sbc}{c}{sbc}{}
\DeclareFontSeriesChangeRule {sbc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {sbc}{ec}{sbec}{sbc}
\DeclareFontSeriesChangeRule {sbc}{el}{elc}{}
\DeclareFontSeriesChangeRule {sbc}{l}{lc}{}
\DeclareFontSeriesChangeRule {sbc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {sbc}{sc}{sbsc}{sbc}
\DeclareFontSeriesChangeRule {sbc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {sbc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {sbc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {sbc}{x}{sbx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {sbx}{b}{bx}{}
\DeclareFontSeriesChangeRule {sbx}{c}{sbc}{}
\DeclareFontSeriesChangeRule {sbx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {sbx}{ec}{sbec}{}
\DeclareFontSeriesChangeRule {sbx}{el}{elx}{}
\DeclareFontSeriesChangeRule {sbx}{l}{lx}{}
\DeclareFontSeriesChangeRule {sbx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {sbx}{sc}{sbsc}{}
\DeclareFontSeriesChangeRule {sbx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {sbx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {sbx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {sbx}{x}{sbx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {sb}{c} {sbc} {bc} %? %<-----
\DeclareFontSeriesChangeRule {sb}{ec} {sbec} {sbc} %? %<-----
\DeclareFontSeriesChangeRule {sb}{sc} {sbsc} {sbc} %? %<-----
\DeclareFontSeriesChangeRule {sb}{x} {sbx} {bx} %? %<-----
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {slc}{b}{bc}{}
\DeclareFontSeriesChangeRule {slc}{c}{slc}{}
\DeclareFontSeriesChangeRule {slc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {slc}{ec}{slec}{}
\DeclareFontSeriesChangeRule {slc}{el}{elc}{}
\DeclareFontSeriesChangeRule {slc}{l}{lc}{}
\DeclareFontSeriesChangeRule {slc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {slc}{sc}{slsc}{}
\DeclareFontSeriesChangeRule {slc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {slc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {slc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {slc}{x}{slx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {slx}{b}{bx}{}
\DeclareFontSeriesChangeRule {slx}{c}{slc}{}
\DeclareFontSeriesChangeRule {slx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {slx}{ec}{slec}{}
\DeclareFontSeriesChangeRule {slx}{el}{elx}{}
\DeclareFontSeriesChangeRule {slx}{l}{lx}{}
\DeclareFontSeriesChangeRule {slx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {slx}{sc}{slsc}{}
\DeclareFontSeriesChangeRule {slx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {slx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {slx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {slx}{x}{slx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {sl}{c}{slc}{}
\DeclareFontSeriesChangeRule {sl}{ec}{slec}{}
\DeclareFontSeriesChangeRule {sl}{sc}{slsc}{}
\DeclareFontSeriesChangeRule {sl}{x}{slx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ubc}{b}{bc}{}
\DeclareFontSeriesChangeRule {ubc}{c}{ubc}{}
\DeclareFontSeriesChangeRule {ubc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {ubc}{ec}{ubec}{}
\DeclareFontSeriesChangeRule {ubc}{el}{elc}{}
\DeclareFontSeriesChangeRule {ubc}{l}{lc}{}
\DeclareFontSeriesChangeRule {ubc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {ubc}{sc}{ubsc}{}
\DeclareFontSeriesChangeRule {ubc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {ubc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {ubc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {ubc}{x}{ubx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ubx}{b}{bx}{}
\DeclareFontSeriesChangeRule {ubx}{c}{ubc}{}
\DeclareFontSeriesChangeRule {ubx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {ubx}{ec}{ubec}{}
\DeclareFontSeriesChangeRule {ubx}{el}{elx}{}
\DeclareFontSeriesChangeRule {ubx}{l}{lx}{}
\DeclareFontSeriesChangeRule {ubx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {ubx}{sc}{ubsc}{}
\DeclareFontSeriesChangeRule {ubx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {ubx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {ubx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {ubx}{x}{ubx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ub}{c}{ubc}{}
\DeclareFontSeriesChangeRule {ub}{ec}{ubec}{}
\DeclareFontSeriesChangeRule {ub}{sc}{ubsc}{}
\DeclareFontSeriesChangeRule {ub}{x}{ubx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ulc}{b}{bc}{}
\DeclareFontSeriesChangeRule {ulc}{c}{ulc}{}
\DeclareFontSeriesChangeRule {ulc}{eb}{ebc}{}
\DeclareFontSeriesChangeRule {ulc}{ec}{ulec}{ulc}
\DeclareFontSeriesChangeRule {ulc}{el}{elc}{}
\DeclareFontSeriesChangeRule {ulc}{l}{lc}{}
\DeclareFontSeriesChangeRule {ulc}{sb}{sbc}{}
\DeclareFontSeriesChangeRule {ulc}{sc}{ulsc}{ulc}
\DeclareFontSeriesChangeRule {ulc}{sl}{slc}{}
\DeclareFontSeriesChangeRule {ulc}{ub}{ubc}{}
\DeclareFontSeriesChangeRule {ulc}{ul}{ulc}{}
\DeclareFontSeriesChangeRule {ulc}{x}{ulx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ulx}{b}{bx}{}
\DeclareFontSeriesChangeRule {ulx}{c}{ulc}{}
\DeclareFontSeriesChangeRule {ulx}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {ulx}{ec}{ulec}{}
\DeclareFontSeriesChangeRule {ulx}{el}{elx}{}
\DeclareFontSeriesChangeRule {ulx}{l}{lx}{}
\DeclareFontSeriesChangeRule {ulx}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {ulx}{sc}{ulsc}{}
\DeclareFontSeriesChangeRule {ulx}{sl}{slx}{}
\DeclareFontSeriesChangeRule {ulx}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {ulx}{ul}{ulx}{}
\DeclareFontSeriesChangeRule {ulx}{x}{ulx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {ul}{c}{ulc}{}
\DeclareFontSeriesChangeRule {ul}{ec}{ulec}{}
\DeclareFontSeriesChangeRule {ul}{sc}{ulsc}{}
\DeclareFontSeriesChangeRule {ul}{x}{ulx}{}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareFontSeriesChangeRule {x}{b}{bx}{}
\DeclareFontSeriesChangeRule {x}{c}{c}{}
\DeclareFontSeriesChangeRule {x}{eb}{ebx}{}
\DeclareFontSeriesChangeRule {x}{ec}{ec}{}
\DeclareFontSeriesChangeRule {x}{el}{elx}{}
\DeclareFontSeriesChangeRule {x}{l}{lx}{}
\DeclareFontSeriesChangeRule {x}{sb}{sbx}{}
\DeclareFontSeriesChangeRule {x}{sc}{sc}{}
\DeclareFontSeriesChangeRule {x}{sl}{slx}{}
\DeclareFontSeriesChangeRule {x}{ub}{ubx}{}
\DeclareFontSeriesChangeRule {x}{ul}{ulx}{}
% \end{macrocode}
%
%
% Special rules for \texttt{lm} etc.\ aren't needed because if the
% target \texttt{lm} is request it will used if there is no rule
% and that id then reduced to \texttt{l}
% automatically. Same for \texttt{mc} and friends. Only \texttt{?m}
% and \texttt{m?} need rules.
%
% So here are the special rules for \texttt{m?}:
% \begin{macrocode}
\DeclareFontSeriesChangeRule {bc}{m?}{c}{}
\DeclareFontSeriesChangeRule {bec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {bsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {bx}{m?}{x}{}
\DeclareFontSeriesChangeRule {b}{m?}{m}{}
\DeclareFontSeriesChangeRule {c}{m?}{c}{}
\DeclareFontSeriesChangeRule {ebc}{m?}{c}{}
\DeclareFontSeriesChangeRule {ebec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {ebsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {ebx}{m?}{x}{}
\DeclareFontSeriesChangeRule {eb}{m?}{m}{}
\DeclareFontSeriesChangeRule {ec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {elc}{m?}{c}{}
\DeclareFontSeriesChangeRule {elec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {elsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {elx}{m?}{x}{}
\DeclareFontSeriesChangeRule {el}{m?}{m}{}
\DeclareFontSeriesChangeRule {lc}{m?}{c}{}
\DeclareFontSeriesChangeRule {lec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {lsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {lx}{m?}{x}{}
\DeclareFontSeriesChangeRule {l}{m?}{m}{}
\DeclareFontSeriesChangeRule {m}{m?}{m}{}
\DeclareFontSeriesChangeRule {sbc}{m?}{c}{}
\DeclareFontSeriesChangeRule {sbec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {sbsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {sbx}{m?}{x}{}
\DeclareFontSeriesChangeRule {sb}{m?}{m}{}
\DeclareFontSeriesChangeRule {sc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {slc}{m?}{c}{}
\DeclareFontSeriesChangeRule {slec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {slsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {slx}{m?}{x}{}
\DeclareFontSeriesChangeRule {sl}{m?}{m}{}
\DeclareFontSeriesChangeRule {ubc}{m?}{c}{}
\DeclareFontSeriesChangeRule {ubec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {ubsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {ubx}{m?}{x}{}
\DeclareFontSeriesChangeRule {ub}{m?}{ub}{}
\DeclareFontSeriesChangeRule {ulc}{m?}{c}{}
\DeclareFontSeriesChangeRule {ulec}{m?}{ec}{}
\DeclareFontSeriesChangeRule {ulsc}{m?}{sc}{}
\DeclareFontSeriesChangeRule {ulx}{m?}{x}{}
\DeclareFontSeriesChangeRule {ul}{m?}{m}{}
\DeclareFontSeriesChangeRule {x}{m?}{x}{}
% \end{macrocode}
%
% And there the special rules for \texttt{?m}:
% \begin{macrocode}
\DeclareFontSeriesChangeRule {bc}{?m}{b}{}
\DeclareFontSeriesChangeRule {bec}{?m}{b}{}
\DeclareFontSeriesChangeRule {bsc}{?m}{b}{}
\DeclareFontSeriesChangeRule {bsc}{?m}{b}{}
\DeclareFontSeriesChangeRule {bx}{?m}{b}{}
\DeclareFontSeriesChangeRule {b}{?m}{b}{}
\DeclareFontSeriesChangeRule {c}{?m}{m}{}
\DeclareFontSeriesChangeRule {ebc}{?m}{eb}{}
\DeclareFontSeriesChangeRule {ebec}{?m}{eb}{}
\DeclareFontSeriesChangeRule {ebsc}{?m}{eb}{}
\DeclareFontSeriesChangeRule {ebsc}{?m}{eb}{}
\DeclareFontSeriesChangeRule {ebx}{?m}{eb}{}
\DeclareFontSeriesChangeRule {eb}{?m}{eb}{}
\DeclareFontSeriesChangeRule {ec}{?m}{m}{}
\DeclareFontSeriesChangeRule {elc}{?m}{el}{}
\DeclareFontSeriesChangeRule {elec}{?m}{el}{}
\DeclareFontSeriesChangeRule {elsc}{?m}{el}{}
\DeclareFontSeriesChangeRule {elsc}{?m}{el}{}
\DeclareFontSeriesChangeRule {elx}{?m}{el}{}
\DeclareFontSeriesChangeRule {el}{?m}{el}{}
\DeclareFontSeriesChangeRule {lc}{?m}{l}{}
\DeclareFontSeriesChangeRule {lec}{?m}{l}{}
\DeclareFontSeriesChangeRule {lsc}{?m}{l}{}
\DeclareFontSeriesChangeRule {lsc}{?m}{l}{}
\DeclareFontSeriesChangeRule {lx}{?m}{l}{}
\DeclareFontSeriesChangeRule {l}{?m}{l}{}
\DeclareFontSeriesChangeRule {m}{?m}{m}{}
\DeclareFontSeriesChangeRule {sbc}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sbec}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sbsc}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sbsc}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sbx}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sb}{?m}{sb}{}
\DeclareFontSeriesChangeRule {sc}{?m}{m}{}
\DeclareFontSeriesChangeRule {sc}{?m}{m}{}
\DeclareFontSeriesChangeRule {slc}{?m}{sl}{}
\DeclareFontSeriesChangeRule {slec}{?m}{sl}{}
\DeclareFontSeriesChangeRule {slsc}{?m}{sl}{}
\DeclareFontSeriesChangeRule {slsc}{?m}{sl}{}
\DeclareFontSeriesChangeRule {slx}{?m}{sl}{}
\DeclareFontSeriesChangeRule {sl}{?m}{sl}{}
\DeclareFontSeriesChangeRule {ubc}{?m}{ub}{}
\DeclareFontSeriesChangeRule {ubec}{?m}{ub}{}
\DeclareFontSeriesChangeRule {ubsc}{?m}{ub}{}
\DeclareFontSeriesChangeRule {ubsc}{?m}{ub}{}
\DeclareFontSeriesChangeRule {ubx}{?m}{ub}{}
\DeclareFontSeriesChangeRule {ub}{?m}{m}{}
\DeclareFontSeriesChangeRule {ulc}{?m}{ul}{}
\DeclareFontSeriesChangeRule {ulec}{?m}{ul}{}
\DeclareFontSeriesChangeRule {ulsc}{?m}{ul}{}
\DeclareFontSeriesChangeRule {ulsc}{?m}{ul}{}
\DeclareFontSeriesChangeRule {ulx}{?m}{ul}{}
\DeclareFontSeriesChangeRule {ul}{?m}{ul}{}
\DeclareFontSeriesChangeRule {x}{?m}{m}{}
% \end{macrocode}
%
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\DeclareFontSeriesChangeRule}{Series change rules}%
%<latexrelease>
%<latexrelease>\let\DeclareFontSeriesChangeRule\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
%
%
%
%
% \subsection{Changing to a new series}
%
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2021/06/01}%
%<latexrelease> {\fontseries}{delay fontseries update}%
% \end{macrocode}
%
%
% \begin{macro}{\fontseries}
% The \cs{fontseries} command takes one argument which is the requested new
% font series. In the orginal implementation it simply saved the
% expanded value in \cs{f@series}. Now we do a bit more processing
% and look up the final value in the font series data base. This is
% done by \cs{merge@font@series}. But the lookup should be done
% within the target family and call to \cs{fontseries} might be
% followed by a \cs{fontfamily} call. So we delay the processing to
% \cs{selectfont} and only record the necessary action in
% \cs{delayed@f@adjustment}.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
\DeclareRobustCommand\fontseries[1]{\@forced@seriesfalse
\expandafter\def\expandafter\delayed@f@adjustment\expandafter
{\delayed@f@adjustment\delayed@merge@font@series{#1}}}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\delayed@f@adjustment}
% The macro holding the delayed action(s) for use in \cs{selectfont}.
% \begin{macrocode}
\let\delayed@f@adjustment\@empty
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\fontseriesforce}
% To change unconditionally to a new series you can use
% \cs{fontseriesforce}. Of course, if the series doesn't exist for
% the current family substitution still happens, but there is not
% dependency on the current series.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
% \begin{macrocode}
\DeclareRobustCommand\fontseriesforce[1]{\@forced@seriestrue
\expandafter\def\expandafter\delayed@f@adjustment\expandafter
{\delayed@f@adjustment\edef\f@series{#1}}}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\if@forced@series}
% If the series gets forced we need to know that fact later on.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
% \begin{macrocode}
\newif\if@forced@series
% \end{macrocode}
% \end{macro}
%
%
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\fontseries}{delay fontseries update}%
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\fontseries[1]{\@forced@seriesfalse
%<latexrelease> \merge@font@series{#1}}
%<latexrelease>\DeclareRobustCommand\fontseriesforce[1]{\@forced@seriestrue
%<latexrelease> \edef\f@series{#1}}
%<latexrelease>\let\delayed@f@adjustment\@undefined
%<latexrelease>
% \end{macrocode}
% For a roll forward we may have to define \cs{if@forced@series}
% but this needs doing in a way that \TeX{} doesn't see it when
% skipping over conditionals.
% \changes{v1.0i}{2021/03/18}
% {Fix rollforward definition.}
% \begin{macrocode}
%<latexrelease>\expandafter\newif\csname if@forced@series\endcsname
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\fontseries}{delay fontseries update}%
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\fontseries[1]{\edef\f@series{#1}}
%<latexrelease>\let\fontseriesforce\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
%
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\merge@font@series}{Merge series values}%
% \end{macrocode}
%
%
% \begin{macro}{\merge@font@series}
% We look up the data base value by expanding the right command
% twice. If no such value exist then the result will be \cs{relax}
% otherwise it will be the two brace groups: the desired result and
% the alternate result. The first case means that the third
% argument to \cs{merge@font@series} will be empty.
% \begin{macrocode}
\def\merge@font@series#1{%
\expandafter\expandafter\expandafter
\merge@font@series@
\csname series@\f@series @#1\endcsname
{#1}%
\@nil
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\merge@font@series@}
% This now defines the new \cs{f@series}:
% \begin{macrocode}
\def\merge@font@series@#1#2#3\@nil{%
% \end{macrocode}
% If the third argument is empty there is no database entry for the
% combination and the second argument holds the new series so we
% return that.
%
% Originally the test was simply \verb=\ifx!#3!= but that actually
% dies if \texttt{\#3} starts with a conditional and in the
% definition of \cs{AmSfont} that is actually the case.
% \begin{macrocode}
%\ifcat\expandafter X\detokenize{#1}X%
\def\reserved@a{#3}%
\ifx\reserved@a\@empty
\set@target@series{#2}%
\else
% \end{macrocode}
% Otherwise we check if the desired result for the series
% (\texttt{\#1}) exists for the font family and the current shape.
% All this happens inside \cs{selectfont} which has already taken care to load
% the \texttt{.fd}, file if necessary.
% \begin{macrocode}
\edef\reserved@a{\f@encoding /\f@family /#1/\f@shape}%
\ifcsname \reserved@a \endcsname
% \end{macrocode}
% If the desired result is available then we use that. However, we
% do need some post-processing because we need to drop surplus
% \texttt{m}s due to the way naming convention was designed in the
% '90s (sigh).
% \begin{macrocode}
\set@target@series{#1}%
% \end{macrocode}
% If not, then we try the alternate result (\texttt{\#2}).
% \begin{macrocode}
\else
\ifcsname \f@encoding /\f@family /#2/\f@shape \endcsname
% \end{macrocode}
% If the alternate result exist we use that and also issue a
% warning (or rather a log entry) that we didn't managed to change
% to the desired font.
% \begin{macrocode}
\set@target@series{#2}%
\@font@shape@subst@warning
% \end{macrocode}
% If that doesn't exist either, then we use the requested series unmodified
% (again with a warning).
% \begin{macrocode}
\else
\set@target@series{#3}%
\@font@shape@subst@warning
\fi
\fi
\fi
}
% \end{macrocode}
% It is possible that the previous font and the new one are
% actually identical (and the font was not found because it still
% needs loading) in which case a warning would look rather odd. So
% we make a quick check for that (which is the reason why we
% defined \cs{@reserveda} above instead of doing inline testing
% inside \cs{ifcsname}).
% \begin{macrocode}
\def\@font@shape@subst@warning{%
\edef\reserved@b{\curr@fontshape}%
\ifx\reserved@a\reserved@b \else
\@font@warning{Font shape `\reserved@a' undefined\MessageBreak
using `\reserved@b' instead}%
\fi
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\merge@font@series@without@substitution,
% \merge@font@series@without@substitution@,
% \delayed@merge@font@series}
%
% \changes{v1.0h}{2020/12/22}{Distangle series and shape update (gh/444)}
%
% \cs{merge@font@series@without@substitution} works like
% \cs{merge@font@series}, i.e., it looks up the combination in the
% rule base and if there exists an entry it uses it and if not it
% uses the new series value. However, it doesn't check if there is
% actually a font face with the new series value as
% \cs{merge@font@series} does. This simplified command is used in
% \cs{selectfont} at a point where other font attributes are not
% yet updated so that checking the font face might result incorrect
% in substitutions.
%
% \begin{macrocode}
\def\merge@font@series@without@substitution#1{%
\expandafter\expandafter\expandafter
\merge@font@series@without@substitution@
\csname series@\f@series @#1\endcsname
{#1}%
\@nil
}
% \end{macrocode}
%
% \begin{macrocode}
\def\merge@font@series@without@substitution@#1#2#3\@nil{%
\def\reserved@a{#3}%
\ifx\reserved@a\@empty
\set@target@series{#2}%
\else
\set@target@series{#1}%
\fi
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\delayed@merge@font@series}
%
% When we delay the merge action in \cs{fontseries} we first
% attempt to use merging without substitution. If that results in a
% non-existing font face the merge is redone in \cs{selectfont}
% using a version with substitution. See \cs{selectfont} for details.
%
% \changes{v1.0h}{2020/12/22}{Distangle series and shape update
% (gh/444)}
% \begin{macrocode}
\let\delayed@merge@font@series\merge@font@series@without@substitution
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\maybe@load@fontshape}
% A small helper that we use a couple of times: try loading a
% fontshape (in a group because \cs{try@load@fontshape} normalizes
% catcodes and we also want to change \cs{typeout} so that it
% doesn't report missing \texttt{.fd} files on the terminal).
% \begin{macrocode}
\def\maybe@load@fontshape{%
\begingroup
\let \typeout \@font@info
\try@load@fontshape
\endgroup}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\set@target@series}
%
% Finally the code for normalizing the \cs{f@series} value.
%
% The combined series value determined by the mapping may still
% contain an \texttt{m} that we have to remove (as the \texttt{.fd}
% files use \texttt{c} not \texttt{mc} to denote a medium weight
% condensed series, etc.). We do this in all branches above because a user
% might have written
%\begin{verbatim}
% \DeclareFontSeriesChangeRule {m}{sc}{msc}{mc}
%\end{verbatim}
% instead of using \texttt{sc} and \texttt{c} as needed in the
% \texttt{.fd} file.
% \begin{macrocode}
\def\set@target@series#1{%
% \end{macrocode}
% We need to \cs{edef} the argument first in case it starts with a
% conditional. Then we check (and perhaps drop) an ``m'' from the
% value and assign the result to \cs{f@series}.
% \changes{v1.0d}{2020/02/27}{Drop ``m'' only in a specific set of values (gh/293)}
% \begin{macrocode}
\edef\f@series{#1}%
\series@maybe@drop@one@m\f@series\f@series
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\series@maybe@drop@one@m}
% If the series value is in NFSS notation then it should not
% contain any ``m'' unless it is just an ``m'' by it own. So we
% need to drop surplus ``m''s. But we better don't do this for full
% names, such as ``\texttt{semibold}'' as used by
% \texttt{autoinst}, for example. So we test against the possible
% explicit values that should drop an ``m''.
% After that we assign the result to \verb=#2= for further use.
% \changes{v1.0d}{2020/02/27}{Drop ``m'' in certain values from a
% fixed list (gh/293)}
% \begin{macrocode}
\def\series@maybe@drop@one@m#1{%
\expandafter\series@maybe@drop@one@m@x\expandafter{#1}}
% \end{macrocode}
%
% \begin{macrocode}
\def\series@maybe@drop@one@m@x#1#2{%
% \end{macrocode}
% The code below is an inline version of the \cs{in@} macro without
% the group, so that it works in \cs{accent}.
% \begin{macrocode}
\def\in@@##1,#1,{}%
\series@check@toks\expandafter{\in@@
,ulm,elm,lm,slm,mm,sbm,bm,ebm,ubm,muc,mec,mc,msc,msx,mx,mex,mux,{}{},#1,}%
\edef\in@@{\the\series@check@toks}%
\ifx\in@@\@empty
% \end{macrocode}
% The default definition for \cs{bfdefault} etc is actually
% \texttt{b\cs{@empty}} so that we can detect if the user has
% changed the default. However that means a) the above test will
% definitely fail (maybe something to change) and b) we better use
% \cs{edef} on the next line to get rid of it as otherwise the test
% against \verb=#2= (e.g. \cs{bfdef@ult}) will fail in other places.
% \changes{v1.0e}{2020/05/19}{Need to use \cs{edef} (gh/336)}
% \begin{macrocode}
\edef#2{#1}%
\else
\edef#2{\expandafter\series@drop@one@m #1m\series@drop@one@m}%
\fi
}
% \end{macrocode}
% As a precaution we use a private toks register not \cs{toks@} as
% that is no longer hidden inside the group.
% \begin{macrocode}
\newtoks\series@check@toks
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\series@drop@one@m}
% Drop up to two \texttt{m}s but keep one if that makes the series
% value empty. Actually, with the current implementation we know
% that there is at least one in the series value itself and we
% added one after it, so all we have to do is now returning
% \verb=#1#2= and dropping the rest.
% \begin{macrocode}
\def\series@drop@one@m#1m#2m#3\series@drop@one@m{%
% \ifx\relax#1#2\relax m\else#1#2\fi
#1#2%
}
% \end{macrocode}
% \end{macro}
%
%
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\merge@font@series}{Merge series values}%
%<latexrelease>
%<latexrelease>\let\merge@font@series\@undefined
%<latexrelease>\let\merge@font@series@\@undefined
%<latexrelease>\let\@font@shape@subst@warning\@undefined
%<latexrelease>\let\merge@font@series@without@substitution\@undefined
%<latexrelease>\let\merge@font@series@without@substitution@\@undefined
%<latexrelease>\let\delayed@merge@font@series\@undefined
%<latexrelease>\let\maybe@load@fontshape\@undefined
%<latexrelease>\let\set@target@series\@undefined
%<latexrelease>\let\series@maybe@drop@one@m\@undefined
%<latexrelease>\let\series@drop@one@m\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \section{Changing the shape}
%
% Shapes are also split in two axes (though it could be more if
% that is desirable), essentially building in an ``sc''
% axis).
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\DeclareFontShapeChangeRule}{Font shape change rules}%
% \end{macrocode}
%
%
%
% \begin{macro}{\DeclareFontShapeChangeRule}
% The database for shapes is done in exactly the same way, only
% that it is much smaller and we usually have no alternative shape
% (or rather it is empty thus not used).
% \begin{macrocode}
\def\DeclareFontShapeChangeRule #1#2#3#4{%
\@namedef{shape@#1@#2}{{#3}{#4}}}
% \end{macrocode}
% \end{macro}
%
%
% There is kind of the same problem with returning back from
% \texttt{sc} to normal. It sort of needs its own letter. In
% \texttt{fontspec} this was solved by the first time \cs{upshape} changes
% \texttt{it} or \texttt{sl} back (so only \texttt{sc} remains) and
% second time it changes then \texttt{sc} back to normal. Maybe
% that's not a bad way to handle it, but decided for a slightly
% different approach: \texttt{n} always returns to ``normal'', ie
% resets everything and \texttt{up} changes italic or slanted to
% upright and \texttt{ulc} undoes small caps.
%
% So we now offer \cs{normalshape} (using \cs{shapedefault} which
% is normally the same as calling both \cs{ulcshape} and
% \cs{upshape}, only more efficient.
%
%
% \begin{macro}{\ulcshape}
% \begin{macro}{\textulc}
% \begin{macro}{\ulcdefault}
% To request going back to upper/lowercase we need a new
% command. It uses \texttt{ulc} as shape name but this shape is
% virtual, i.e., it doesn't exist as a real shape, it is only used
% as part of the database table entries and thus only appears in
% the second argument there (but not in the first).
% \begin{macrocode}
\DeclareRobustCommand\ulcshape
{\not@math@alphabet\ulcshape\relax
\fontshape\ulcdefault\selectfont}
\let\ulcdefault\@undefined % for rollback
\newcommand\ulcdefault{ulc}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\swshape}
% \begin{macro}{\textsw}
% \begin{macro}{\swdefault}
% New command to select a swash shape. The standard rules put this
% in the same category as italics or slanted, i.e., if you ask for
% it then italics are undone. One could provide more complicated
% rules so that \texttt{it} + \texttt{sw} becomes \texttt{swit} but
% given that there are only very few fonts that have swash letters
% that level of flexibility (these days) would be just resulting in
% a lot of combinations that do not exist.
% \begin{macrocode}
\DeclareRobustCommand\swshape
{\not@math@alphabet\swshape\relax
\fontshape\swdefault\selectfont}
\let\swdefault\@undefined % for rollback
\newcommand\swdefault{sw}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\sscshape}
% \begin{macro}{\textssc}
% \begin{macro}{\sscdefault}
% New command to select spaced small capitals. This is only here
% because \texttt{fontaxes} offered it. There isn't a single free
% font that supports it. However, some commercial ones do, so we
% offer it so that at some point \texttt{fontaxes} could be
% retired.
%
% So far there aren't any rules for it---probably there should be
% some putting it in the same category as \texttt{sc}.
% \begin{macrocode}
\DeclareRobustCommand\sscshape
{\not@math@alphabet\sscshape\relax
\fontshape\sscdefault\selectfont}
\let\sscdefault\@undefined % for rollback
\newcommand\sscdefault{ssc}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \subsection{Mapping rules for shape combinations}
%
% Many of the entries are commented out as we will get that result
% without any entry.
% \begin{macrocode}
%\DeclareFontShapeChangeRule {n}{n} {n} {}
\DeclareFontShapeChangeRule {n}{it} {it} {sl}
\DeclareFontShapeChangeRule {n}{sl} {sl} {it}
%\DeclareFontShapeChangeRule {n}{sw} {sw} {}
%\DeclareFontShapeChangeRule {n}{sc} {sc} {}
\DeclareFontShapeChangeRule {n}{ulc} {n} {}
\DeclareFontShapeChangeRule {n}{up} {n} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {it}{n} {n} {}
%\DeclareFontShapeChangeRule {it}{it} {it} {}
\DeclareFontShapeChangeRule {it}{sl} {sl} {it}
%\DeclareFontShapeChangeRule {it}{sw} {sw} {}
% \end{macrocode}
% If neither \texttt{scit} nor \texttt{scsl} exist then \texttt{sc}
% will be used as a fallback albeit with a log entry, so except for
% the latter there will be no change for CM or Latin Modern fonts.
% \begin{macrocode}
\DeclareFontShapeChangeRule {it}{sc} {scit} {scsl}
\DeclareFontShapeChangeRule {it}{ulc} {it} {}
\DeclareFontShapeChangeRule {it}{up} {n} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {sl}{n} {n} {}
\DeclareFontShapeChangeRule {sl}{it} {it} {sl}
%\DeclareFontShapeChangeRule {sl}{sl} {sl} {}
%\DeclareFontShapeChangeRule {sl}{sw} {sw} {}
\DeclareFontShapeChangeRule {sl}{sc} {scsl} {scit}
\DeclareFontShapeChangeRule {sl}{ulc} {sl} {}
\DeclareFontShapeChangeRule {sl}{up} {n} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {sc}{n} {n} {}
\DeclareFontShapeChangeRule {sc}{it} {scit} {scsl}
\DeclareFontShapeChangeRule {sc}{sl} {scsl} {scit}
\DeclareFontShapeChangeRule {sc}{sw} {scsw} {sw}
%\DeclareFontShapeChangeRule {sc}{sc} {sc} {}
\DeclareFontShapeChangeRule {sc}{ulc} {n} {}
% \end{macrocode}
%
% The next rule might be a bit surprising and rightly so. Correct
% would be that \texttt{sc} is not affected by \texttt{up}, i.e.,
% remains \texttt{sc} as showed in the commented out rule. However,
% for nearly three decades commands such as \cs{sc} or
% \cs{textup} changed small caps back to the ``normal'' shape. So
% for backward compatibility we keep that behavior.
%
% As a result you are currently typesetting in \texttt{scit} or
% \texttt{scsl} using \cs{upshape} twice will return you to the
% normal shape too, the first will change to \texttt{sc} and the
% second (because of the rule below) change that to
% \texttt{n}. This is the way \texttt{fontspec} implemented its
% version on this interface, so this rule means we are also
% compatible with the way \texttt{fontspec} behaved. Still it
% remains an oddity which I would rather liked to have avoided.
% \begin{macrocode}
%\DeclareFontShapeChangeRule {sc}{up} {sc} {}
\DeclareFontShapeChangeRule {sc}{up} {n} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {scit}{n} {n} {}
\DeclareFontShapeChangeRule {scit}{it} {scit} {}
\DeclareFontShapeChangeRule {scit}{sl} {scsl} {scit}
\DeclareFontShapeChangeRule {scit}{sw} {scsw} {sc} % or scit?
\DeclareFontShapeChangeRule {scit}{sc} {scit} {}
\DeclareFontShapeChangeRule {scit}{ulc} {it} {}
\DeclareFontShapeChangeRule {scit}{up} {sc} {}
% \end{macrocode}
% The previous rule assumes that if \texttt{scit} exists then
% \texttt{it} exists as well. If not, the mechanism will save
% \texttt{ulc} in \cs{f@series} which most certainly doesn't
% exist. So when a font is later selected that would result in a
% substitution (so no harm done really). Alternatively, we could in
% this case use \texttt{n} as alternative, which may be a bit
% faster, but such a setup would be so weird in the first place
% that this isn't worth the effort.
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {scsl}{n} {n} {}
\DeclareFontShapeChangeRule {scsl}{it} {scit} {scsl}
\DeclareFontShapeChangeRule {scsl}{sl} {scsl} {}
\DeclareFontShapeChangeRule {scsl}{sw} {scsw} {sc} % or scsl?
\DeclareFontShapeChangeRule {scsl}{sc} {scsl} {}
\DeclareFontShapeChangeRule {scsl}{ulc} {sl} {}
\DeclareFontShapeChangeRule {scsl}{up} {sc} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {scsw}{n} {n} {}
\DeclareFontShapeChangeRule {scsw}{it} {scit} {scsw}
\DeclareFontShapeChangeRule {scsw}{sl} {scsl} {}
\DeclareFontShapeChangeRule {scsw}{sw} {scsw} {}
\DeclareFontShapeChangeRule {scsw}{sc} {scsw} {}
\DeclareFontShapeChangeRule {scsw}{ulc} {sw} {}
\DeclareFontShapeChangeRule {scsw}{up} {sc} {}
% \end{macrocode}
%
% \begin{macrocode}
%\DeclareFontShapeChangeRule {sw}{n} {n} {}
%\DeclareFontShapeChangeRule {sw}{it} {it} {}
%\DeclareFontShapeChangeRule {sw}{sl} {sl} {}
%\DeclareFontShapeChangeRule {sw}{sw} {sw} {}
\DeclareFontShapeChangeRule {sw}{sc} {scsw} {}
\DeclareFontShapeChangeRule {sw}{ulc} {sw} {}
\DeclareFontShapeChangeRule {sw}{up} {n} {}
% \end{macrocode}
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\DeclareFontShapeChangeRule}{Font shape change rules}%
%<latexrelease>
%<latexrelease>\let\DeclareFontShapeChangeRule\@undefined
%<latexrelease>\let\ulcshape\@undefined
%<latexrelease>\let\ulcdefault\@undefined
%<latexrelease>\let\swshape\@undefined
%<latexrelease>\let\swdefault\@undefined
%<latexrelease>\let\sscshape\@undefined
%<latexrelease>\let\sscdefault\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
%
% \subsection{Changing to a new shape}
%
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2021/06/01}%
%<latexrelease> {\fontshape}{Font shape change}%
% \end{macrocode}
%
%
%
% \begin{macro}{\fontshape}
% Again the \cs{fontshape} now has to do a lookup to get to its new
% value in \cs{f@shape}. The method is exactly the same as in
% \cs{fontseries}.
% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
\DeclareRobustCommand\fontshape[1]
{\expandafter\def\expandafter\delayed@f@adjustment\expandafter
{\delayed@f@adjustment\delayed@merge@font@shape{#1}}}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\fontshapeforce}
% The unconditional version:
%
% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
\DeclareRobustCommand\fontshapeforce[1]
{\expandafter\def\expandafter\delayed@f@adjustment\expandafter
{\delayed@f@adjustment\edef\f@shape{#1}}}
% \end{macrocode}
% \end{macro}
%
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\fontshape}{Font shape change}%
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\fontshape[1]{\merge@font@shape{#1}}
%<latexrelease>\DeclareRobustCommand\fontshapeforce[1]{\edef\f@shape{#1}}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\fontshape}{Font shape change}%
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\fontshape [1]{\edef\f@shape{#1}}
%<latexrelease>\let\fontshapeforce\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\merge@font@shape}{Font shape change rules}%
% \end{macrocode}
%
%
%
% \begin{macro}{\merge@font@shape}
% Look up the database entry (if existing) and act accordingly.
% \begin{macrocode}
\def\merge@font@shape#1{%
\expandafter\expandafter\expandafter
\merge@font@shape@
\csname shape@\f@shape @#1\endcsname
{#1}%
\@nil
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\merge@font@shape@}
% Same game now, except that we look at shapes not series values
% and we can set the shape without the complication of dropping
% ``m''s from the name as we had to for the series.
% \begin{macrocode}
\def\merge@font@shape@#1#2#3\@nil{%
\def\reserved@a{#3}%
\ifx\reserved@a\@empty
\edef\f@shape{#2}%
\else
% \end{macrocode}
% \cs{reserved@a} is used in \cs{@font@shape@subst@warning} so we
% have to define it in addition to do the \cs{ifcsname} test
% \begin{macrocode}
\edef\reserved@a{\f@encoding /\f@family /\f@series/#1}%
\ifcsname \reserved@a\endcsname
\edef\f@shape{#1}%
\else
\ifcsname \f@encoding /\f@family /\f@series/#2\endcsname
\edef\f@shape{#2}%
\@font@shape@subst@warning
\else
\edef\f@shape{#3}%
\@font@shape@subst@warning
\fi
\fi
\fi
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\merge@font@shape@without@substitution,
% \merge@font@shape@without@substitution@,
% \delayed@merge@font@shape}
% See definition of \cs{selectfont} for how these macros are used.
% \changes{v1.0h}{2020/12/22}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
\def\merge@font@shape@without@substitution#1{%
\expandafter\expandafter\expandafter
\merge@font@shape@without@substitution@
\csname shape@\f@shape @#1\endcsname
{#1}%
\@nil
}
% \end{macrocode}
%
% \begin{macrocode}
\def\merge@font@shape@without@substitution@#1#2#3\@nil{%
\def\reserved@a{#3}%
\ifx\reserved@a\@empty
\edef\f@shape{#2}%
\else
\edef\f@shape{#1}%
\fi
}
% \end{macrocode}
%
% \begin{macrocode}
\let\delayed@merge@font@shape\merge@font@shape@without@substitution
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\normalshape}
%
% \cs{normalshape} resets both sub-axes if the default rules are used.
% \begin{macrocode}
\protected\def\normalshape
{\not@math@alphabet\normalshape\relax
\fontshape\shapedefault\selectfont}%
% \end{macrocode}
% \end{macro}
%
%
%
%
% \section{Make sure we win \ldots}
%
% This code implements one aspect of what the package \textsf{fontaxes}
% provide. So its redefinitions for the various shape commands,
% such as \cs{itshape} should no longer happen. We therefore force
% the standard definitions at \cs{AtBeginDocument} (later when this
% is defined. Once
% \texttt{fontaxes} is no longer doing such redefinitions that could
% be taken out again.
%
% We use a separate macro so that we can easily disable this (in
% case of rollback).
%
% \begin{macro}{\reinstall@nfss@defs}
%
% I use \cs{protected} here not \cs{DeclareRobustCommand} to avoid
% extra status lines.
% \begin{macrocode}
\def\reinstall@nfss@defs{%
\protected\def\upshape
{\not@math@alphabet\upshape\relax
\fontshape\updefault\selectfont}%
\protected\def\slshape
{\not@math@alphabet\slshape\relax
\fontshape\sldefault\selectfont}%
\protected\def\scshape
{\not@math@alphabet\scshape\relax
\fontshape\scdefault\selectfont}%
\protected\def\itshape
{\not@math@alphabet\itshape\mathit
\fontshape\itdefault\selectfont}%
\protected\def\ulcshape
{\not@math@alphabet\ulcshape\relax
\fontshape{ulc}\selectfont}%
\protected\def\swshape
{\not@math@alphabet\swshape\relax
\fontshape\swdefault\selectfont}%
\protected\def\sscshape
{\not@math@alphabet\sscshape\relax
\fontshape\sscdefault\selectfont}%
}
% \end{macrocode}
% \end{macro}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\merge@font@shape}{Font shape change rules}%
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\fontshape [1]{\edef\f@shape{#1}}
%<latexrelease>\let\fontshapeforce\@undefined
%<latexrelease>
%<latexrelease>\let\merge@font@shape\@undefined
%<latexrelease>\let\merge@font@shape@\@undefined
%<latexrelease>
%<latexrelease>\let\merge@font@shape@without@substitution\@undefined
%<latexrelease>\let\merge@font@shape@without@substitution@\@undefined
%<latexrelease>\let\delayed@merge@font@shape\@undefined
%<latexrelease>
%<latexrelease>\let\normalshape\@undefined
%<latexrelease>
% \end{macrocode}
% This is always called in \cs{document} so don't make it undefined.
% \begin{macrocode}
%<latexrelease>
%<latexrelease>\let\reinstall@nfss@defs\relax
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
%
%
% This initializes the 2020/02/02 extensions to NFSS after any changes
% in the preamble.
% \changes{v1.0g}{2020/08/21}{Integration of new hook management interface}
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
\g@addto@macro\@kernel@after@begindocument@before
{\reinstall@nfss@defs\init@series@setup}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% The initialization was introduced in 2020/02/02 but
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
%<latexrelease>\AtBeginDocument{\reinstall@nfss@defs\init@series@setup}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%</2ekernel>
% \end{macrocode}
%
% \Finale
%