% \iffalse meta-comment % % Copyright (C) 1993-2024 % 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: ltfsstrc.dtx %% Copyright (C) 1989-97 by Frank Mittelbach and Rainer Sch\"opf. %% Copyright (C) 1994-97 by LaTeX Project. All rights reserved. % %\NeedsTeXFormat{LaTeX2e}[2021/06/01] %\ProvidesPackage{tracefnt} % [2020/12/22 v3.0n Standard LaTeX package (font tracing)] % \fi % \ProvidesFile{ltfsstrc.dtx} % [2024/11/19 v3.0p LaTeX Kernel (NFSS tracing)] % % \iffalse %<+checkmem>\CHECKMEM % \fi % % % % % \changes{v3.0g}{1995/11/28} % {documentation fixes} % \changes{v3.0f}{1995/10/22}{Added `genb' and `sgenb' size functions % to support new DC font naming scheme.} % \changes{v3.0e}{1995/10/20} % {(DPC) Modify autoload code} % \changes{v3.0d}{1995/10/04} % {(DPC) Modify autoload code} % \changes{v3.0b}{1995/05/24} % {(DPC) Fix \cs{ProvidesFile} usage} % \changes{v3.0a}{1995/05/24} % {(DPC) Make file from previous file, tracefnt 1995/05/16 v2.3o} % \changes{v3.0k}{2015/02/21} % {Removed autoload code} % % \changes{v2.3m}{1994/11/18} % {\cs{next} to \cs{reserved@f}} % \changes{v2.3l}{1994/11/17} % {\cs{@tempa} to \cs{reserved@a}} % \changes{v2.3i}{1994/05/20}{Use new error command names} % \changes{v2.3g}{1994/05/13}{Removed typeouts as % \cs{ProvidesPackage} writes to log.} % \changes{v2.3e}{1994/04/27}{Corrected item that was forgotten % in last change.} % \changes{v2.3d}{1994/04/18}{Changed to new error/warning scheme} % \changes{v2.3a}{1994/01/17}{New math font setup} % \changes{v2.2a}{1993/11/11}{Option concept added for LaTeX2e} % \changes{v2.1j}{1993/09/15}{Corrected spelling of \cs{noxpand}.} % \changes{v2.1i}{1993/09/02}{Corrected name of sgen size function.} % \changes{v2.1h}{1993/07/16}{Changed layout of info messages} % \changes{v2.1b}{1993/03/18} % {Changed all \cs{@tempdimb} in \cs{@tempdimx} % to avoid killing \cs{numberline}} % \changes{v2.1b}{1993/03/18} % {Changed all \cs{@tempdima} in \cs{@tempdimb} % to avoid killing \cs{numberline}} % \changes{v1.0l}{1990/04/01}{Part of code moved to fam.dtx.} % \changes{v1.0k}{1990/03/14}{Added code for TeX3.} % \changes{v1.0h}{1990/01/18}{\cs{tracingfonts} meaning changed.} % % \newcommand\module[1]{\texttt{#1}} % \providecommand{\dst}{\textsc{DocStrip}} % \newcommand\Loption[1]{\texttt{#1}} % % \GetFileInfo{ltfsstrc.dtx} % \title{The \texttt{tracefnt} package\thanks % {This file has version number \fileversion, dated % \filedate.} \\ % for use with the new font selection scheme} % \author{Frank Mittelbach \and Rainer Sch\"opf} % % % \MaintainedByLaTeXTeam{latex} % \maketitle % % \section{Introduction} % % This package contains the code for tracing font loading and font % changes. It basically overlays some of the low-level functions of % NFSS with additional code used for tracing. % % The package accepts the following options: % \begin{description} % \item[errorshow] Write all information about font changes etc.\ % only to the transcript file unless an error happens. This means % that information about font substitution will not be shown on the % terminal. % % \item[warningshow] Show all NFSS warnings on the terminal. This % setting corresponds to the default behaviour of NFSS if the % \texttt{tracefnt} package is \emph{not} loaded! % % \item[infoshow] Show all NFSS warning and all NFSS info % messages (that are normally only written to the transcript file) % also on the terminal. This is the default if the \texttt{tracefnt} % package is loaded. % % \item[debugshow] In addition to \texttt{infoshow} show also % changing of math fonts as far as possible (this option can produce a % large amount of output). % % \item[loading] Show the name of external fonts when they are % loaded. This option shows only ``newly'' loaded fonts not those % already preloaded in the format or the class file before the % \texttt{tracefnt} package became active. % % \item[pausing] % Turn all font warnings into errors so that \LaTeX{} will stop. % % \end{description} % % % \MaybeStop{} % % \section{A driver for this document} % % The next bit of code contains the documentation driver file for % \TeX{}, i.e., the file that will produce the documentation you % are currently reading. It will be extracted from this file by the % \dst{} program. % % When this file is processed directly by \LaTeX{} this will % produce the documentation as well. % % \begin{macrocode} %<*driver> \documentclass{ltxdoc} %\OnlyDescription % comment out for implementation details \begin{document} \DocInput{ltfsstrc.dtx} \end{document} % % \end{macrocode} % % % \section{The Implementation} % % \begin{quote} % \textbf{Warning:} Read the macro documentation with a grain of % salt. It is still basically the documentation from the first NFSS % release and therefore in some cases probably not completely % accurate. % \end{quote} % % If we are making a package file it is a good idea to test whether % we are running under 2e. % This code is actually placed at the very beginning of this file % for easier maintenance, thus commented out here. % \begin{macrocode} %<*package> %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{tracefnt}[??/??/?? v?.?? % Standard LaTeX package (font tracing)] % % \end{macrocode} % % % The \texttt{debug} module makes use of commands contained in a % special package file named \texttt{trace.sty}.\footnote{This package % is not in distribution at the moment (and probably doesn't any % longer work). Think of this part of the code as being historical % artifacts.} % \begin{macrocode} %<+debug> \input trace.sty % \end{macrocode} % % % \section{Handling Options} % % \begin{macro}{\tracingfonts} % Here is the definition of the integer register for the font % trace. As a default in a package file we use $1$ to give error % messages if fonts are substituted. If this code is used for % debugging or tracing reasons in the format file (i.e.\ in % \texttt{fam.dtx}) we use $0$ as the default. But if no font % trace is used we build a definition that will produce a warning % message. % \changes{v1.0l}{1990/04/01} % {Check if \cs{tracingfonts} already defined.} % \changes{v1.0o}{1990/04/01} % {Check if \cs{tracingfonts} defined removed again.} % \begin{macrocode} %<*2ekernel> \message{NFSS tracing,} \def\tracingfonts{% \@font@warning{Command \noexpand\tracingfonts not provided.\MessageBreak Use the `tracefnt' package.\MessageBreak Command found:}% \count@} % % \end{macrocode} % The |\count@| in the line above will remove the number after % |\tracingfonts|. Note that this definition will be overwritten be % the next line if one of these modules are included. % \begin{macrocode} %<*package,trace,debug> \newcount\tracingfonts \tracingfonts=0 % % \end{macrocode} % \end{macro} % % % The option \Loption{errorshow} turns off all warnings so that only % real errors are shown. \Loption{warningshow} corresponds to the % NFSS default (when \texttt{tracefnt} is not loaded). % \Loption{infoshow} is the default for this package here; and % \Loption{debugshow}, \Loption{loading}, and % \Loption{pausing} extend the amount of information even further. % \changes{v2.3o}{1995/05/13} % {Use single hash mark in \cs{DeclareOption}} % \begin{macrocode} %<*package> \DeclareOption{errorshow}{% \def\@font@info#1{% \GenericInfo{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Info: \space\space\space#1}}% \def\@font@warning#1{% \GenericInfo{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Warning: #1}}% } % \end{macrocode} % % \begin{macrocode} \DeclareOption{warningshow}{% \def\@font@info#1{% \GenericInfo{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Info: \space\space\space#1}}% \def\@font@warning#1{% \GenericWarning{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Warning: #1}}% } % \end{macrocode} % % \begin{macrocode} \DeclareOption{infoshow}{% \def\@font@info#1{% \GenericWarning{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Info: \space\space\space#1}}% \def\@font@warning#1{% \GenericWarning{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Warning: #1}}% } % \end{macrocode} % % \begin{macrocode} \DeclareOption{loading}{% \tracingfonts\tw@ } % \end{macrocode} % % \begin{macrocode} \DeclareOption{debugshow}{% \ExecuteOptions{infoshow}% \tracingfonts\thr@@ } % \end{macrocode} % % \changes{v3.0j}{1997/05/29}{Replaced \texttt{\symbol{92}\symbol{92}} % by \cs{MessageBreak}, as suggested by Donald Arseneau.} % \begin{macrocode} \DeclareOption{pausing}{% \def\@font@warning#1{% \GenericError {(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Warning: #1}% {See the LaTeX Companion for details.}% {I'll stop for every LaTeX Font Warning because you requested\MessageBreak the `pausing' option to the tracefnt package.}}% } % \end{macrocode} % We make |infoshow| the default, which in turn defines % |\font@warning| and |\font@info|. % \begin{macrocode} \ExecuteOptions{infoshow} \ProcessOptions % % \end{macrocode} % % We also need a default definition inside the kernel: % \begin{macrocode} %<*2ekernel> \def\@font@info#1{% \GenericInfo{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Info: \space\space\space#1}}% \def\@font@warning#1{% \GenericWarning{(Font)\@spaces\@spaces\@spaces\space\space}% {LaTeX Font Warning: #1}}% % % \end{macrocode} % % % \section{Macros common to \texttt{fam.tex} and \texttt{tracefnt.sty}} % % In the first versions of \texttt{tracefnt.dtx} some macros of % \texttt{fam.dtx}\footnote{This file is currently not distributed in % documented form. Its code is part of \texttt{ltfss.dtx}.} % were redefined to included the extra tracing % information. Now these macros are all defined in this file (i.e.\ % removed from \texttt{fam.dtx}) and different production versions can % be obtained simply by specifying a different set of modules to % include when generating \texttt{ltfss.dtx}. % % % % \subsection{General font loading} % % % \begin{macro}{\extract@font} % % This macro organizes the font loading. % It first calls |\get@external@font| % which will return in |\external@font| the name of the external % font file (the \texttt{.tfm}) as it was determined by the NFSS % tables. % \begin{macrocode} %<*2ekernel|package> \def\extract@font{% \get@external@font % \end{macrocode} % Then the external font is loaded and assigned to the font % identifier stored inside |\font@name| % (for this reason we need |\expandafter|). % \begin{macrocode} \global\expandafter\font\font@name\external@font\relax % \end{macrocode} % When tracing we typeout the internal and external font name. % \changes{v1.0k}{1990/03/14}{Added code for TeX3.} % \begin{macrocode} %<*trace> \ifnum \tracingfonts >\@ne \@font@info{External font `\external@font' loaded as\MessageBreak \font@name}\fi % % \end{macrocode} % Finally we call the corresponding ``loading action'' macros to % finish things. First the font is locally selected to allow the % use of |\font| inside the loading action macros. % \begin{macrocode} \font@name \relax % \end{macrocode} % The next two lines execute the ``loading actions'' for the % family and then for the individual font shape. % \begin{macrocode} \csname \f@encoding+\f@family\endcsname \csname\curr@fontshape\endcsname \relax } % % \end{macrocode} % The |\relax| at the end needs to be explained. % This is inserted to prevent \TeX{} from scanning too far % when it is executing the replacement text of the loading % code macros. % \end{macro} % % % \begin{macro}{\get@external@font} % This function tries to find an external font name. It will place % the name into the macro % |\external@font|. If no font is found it will return the one % that was defined via |\DeclareErrorFont|. % \begin{macrocode} %<*2ekernel> \def\get@external@font{% % \end{macrocode} % We don't know the external font name at the beginning. % \begin{macrocode} \let\external@font\@empty \edef\font@info{\expandafter\expandafter\expandafter\string \csname \curr@fontshape \endcsname}% \try@size@range % \end{macrocode} % If this failed, we'll try to substitute another size of the same % font. This is done by the |\try@size@substitution| macro. It % ``knows about'' |\do@extract@font|, |\font@name|, |\f@size|, and % so on. % \begin{macrocode} \ifx\external@font\@empty \try@size@substitution \ifx\external@font\@empty \@latex@error{Font \expandafter \string\font@name\space not found}\@eha \error@fontshape \get@external@font \fi\fi } % % \end{macrocode} % \end{macro} % % \begin{macrocode} %<*2ekernel|latexrelease|package> %\IncludeInRelease{2021/06/01}% % {\selectfont}{Add hook to \selectfont}% % \end{macrocode} % % % % % \begin{macro}{\selectfont} % \changes{v1.0j}{1990/02/18} % {Redefine unprotected version \cs{p@selectfont} % instead of \cs{selectfont}.} % \changes{v1.1a}{1989/12/16}{Changed order of calls.} % \changes{v2.3f}{1994/05/12}{Use \cs{DeclareRobustCommand}} % The macro |\selectfont| is called whenever a font change must % take place. % \begin{macrocode} \DeclareRobustCommand\selectfont {% % \end{macrocode} % When \module{debug} is specified we actually want something like % `undebug'. The font selection is now stable so that using % |\tracingall| on some other macros will show us a lot of unwanted % information about font loading. Therefore we disable tracing during % font loading as long as |\tracingfonts| is less than $4$. % \changes{v1.0m}{1990/04/05} % {Call \cs{tracingon} only if \cs{tracingfonts} greater than 3.} % \changes{v1.0n}{1990/05/05}{\cs{tracingon} with new syntax.} % \begin{macrocode} %<+debug> \pushtracing %<+debug> \ifnum\tracingfonts<4 \tracingoff %<+debug> \else \tracingon\p@selectfont \fi % \end{macrocode} % If |\baselinestretch| was redefined by the user it will not % longer match its internal counterpart |\f@linespread|. If so we % call |\set@fontsize| to prepare |\size@update|. % \begin{macrocode} \ifx\f@linespread\baselinestretch \else \set@fontsize\baselinestretch\f@size\f@baselineskip \fi % \end{macrocode} % % The series and shape updates are only prepared by % \cs{fontseries} and \cs{fontshape} but not executed until after % we are ready to change the font face. This way they happen after % a possibly new family is set which is important because they % look at the available font faces in that family and alter the % selection based on availability. Several calls to \cs{fontseries} % or \cs{fontshape} are delayed in the order in which they appear, % so that by switching them one can work around missing % intermediate font faces and avoid substitutions. % % We first attempt to do the merge without any substitution. As we % might end up with a non-existing font face we may have to restart % and therefore save the current values of \cs{f@series} and % \cs{f@shape} before the merge. % % But first we make a quick test to see if there are any delayed % actions, because if not it is pointless to make all the % assignments and try loading a missing fontshape. % % \changes{v3.0n}{2020/12/22}{Execute delayed series and shape updates (gh/444)} % \begin{macrocode} \ifx\delayed@f@adjustment\@empty \else \let\f@shape@saved\f@shape \let\f@series@saved\f@series % \end{macrocode} % Then we run the delayed adjustments (which use the % \cs{..@without@substitution} commands): % \begin{macrocode} \delayed@f@adjustment % \end{macrocode} % We then check if the resulting cominbation is valid but for this % we have to make sure that the appropriate \texttt{.fd} is loaded if % that hasn't happened so far. % \begin{macrocode} \maybe@load@fontshape \ifcsname \f@encoding/\f@family/\f@series/\f@shape \endcsname % \end{macrocode} % If this macro is defined then we are good and no further action % is necessary. % % Otherwise the combination is not valid, so we redo the merge but % this time with substitutions. % \begin{macrocode} \else \let\f@shape\f@shape@saved \let\f@series\f@series@saved \let\delayed@merge@font@shape\merge@font@shape \let\delayed@merge@font@series\merge@font@series \delayed@f@adjustment \let\delayed@merge@font@shape\merge@font@shape@without@substitution \let\delayed@merge@font@series\merge@font@series@without@substitution \fi % \end{macrocode} % Now the series and shape values are updated and we clear % \cs{delayed@f@adjustment}. This is important because on the next % execution of \cs{selectfont} we should not mistakenly redo the % delayed actions if there wasn't any series or shape change. % \begin{macrocode} \let\delayed@f@adjustment\@empty \fi % \end{macrocode} % If the series was forced we should now cancel that in case the % next series change is done with some low-level setting to % \cs{f@series}. % \changes{v3.0o}{2021/04/26}{Unset the forced series boolean when reaching % \cs{selectfont} (gh/444)} % \begin{macrocode} \@forced@seriesfalse % \end{macrocode} % Then we generate the internal name of the font % by concatenating {\em family}, {\em series}, % {\em shape}, and current {\em size}, % with slashes as delimiters between them. % This is much more readable than standard % \LaTeX's |\twfbf|, etc. % We define |\font@name| globally, as always. % The reason for this is explained later on. % \changes{v2.0b}{1992/07/26}{} % \begin{macrocode} \xdef\font@name{% \csname\curr@fontshape/\f@size\endcsname}% % \end{macrocode} % We call the macro |\pickup@font| which will load the font if % necessary. % \begin{macrocode} \pickup@font % \end{macrocode} % Then we select the font. % \begin{macrocode} \font@name % \end{macrocode} % % After switching fonts we run a hook, so that packages can make % last minute alterations based on the new font (originally provided % in \pkg{everysel} but using a different interface). % \changes{v3.0m}{2020/12/03}{Install a hook in \cs{selectfont} (gh/444)} % \begin{macrocode} \UseHook{selectfont}% % \end{macrocode} % Finally we call |\size@update|. This macro is normally empty but % will contain actions (like setting the |\baselineskip|) that have % to be carried out when the font size, the base |\baselineskip| or % the |\baselinestretch| have changed. % \begin{macrocode} \size@update % \end{macrocode} % A similar function is called to handle anything related to % encoding updates. This one is changed from |\relax| by % |\fontencoding|. % \changes{v2.3h}{1994/05/14}{Added \cs{enc@update}} % \begin{macrocode} \enc@update % \end{macrocode} % Just before ending this macro we have to pop the tracing stack % if it was pushed before. % \begin{macrocode} %<+debug> \poptracing } % \end{macrocode} % \end{macro} % % % \begin{macro}{selectfont} % Declare the hook used in selecfont in the kernel, but not % inside the \pkg{tracefnt} package. % \begin{macrocode} %<-trace>\NewHook{selectfont} % \end{macrocode} % \end{macro} % % % If |\tracingfonts| is % greater than 2 we also show the font switch inside \cs{selectfont}. % We do this by adding this code to the hook in the \pkg{tracefnt} package: % macro might redefine |\font@name|. % \begin{macrocode} %<*trace> \AddToHook{selectfont} {\ifnum \tracingfonts>\tw@ \@font@info{Switching to \font@name}\fi} % % \end{macrocode} % % % \begin{macrocode} % %\EndIncludeInRelease % \end{macrocode} % % With \cs{selectfont} having different definitions in different % kernels we also have to provide them in the \texttt{tracefnt} % package to support rollback. In packages that works a bit % differently and therefore we have to provide an empty block there. % \begin{macrocode} %\IncludeInRelease{2021/06/01}% % {\selectfont}{Add hook to \selectfont}% %\EndIncludeInRelease % \end{macrocode} % % \begin{macrocode} %\IncludeInRelease{0000/00/00}% % {\selectfont}{Add hook to \selectfont}% % %\DeclareRobustCommand\selectfont % {% % \ifx\f@linespread\baselinestretch \else % \set@fontsize\baselinestretch\f@size\f@baselineskip \fi % \xdef\font@name{% % \csname\curr@fontshape/\f@size\endcsname}% % \pickup@font % \font@name % \size@update % \enc@update % } % %\EndIncludeInRelease % \end{macrocode} % % % % \begin{macro}{\set@fontsize} % The macro |\set@fontsize| does the actual work. First it assigns % new values to |\f@size|, |\f@baselineskip| and |\f@linespread|. % \begin{macrocode} %<*2ekernel|package> \def\set@fontsize#1#2#3{% \@defaultunits\@tempdimb#2pt\relax\@nnil \edef\f@size{\strip@pt\@tempdimb}% \@defaultunits\@tempskipa#3pt\relax\@nnil \edef\f@baselineskip{\the\@tempskipa}% \edef\f@linespread{#1}% % \end{macrocode} % For backward compatibility and for later testing within % |\selectfont| the internal value of |\f@linespread| is passed % back to |\baselinestretch|. % \begin{macrocode} \let\baselinestretch\f@linespread % \end{macrocode} % Additional processing will happen within |\selectfont|. For this % reason the macro |\size@update| (which will be called in % |\selectfont|) will be defined to be: % \begin{macrocode} \def\size@update{% % \end{macrocode} % First calculate the new |\baselineskip| and also store it in % |normalbaselineskip| % \begin{macrocode} \baselineskip\f@baselineskip\relax \baselineskip\f@linespread\baselineskip \normalbaselineskip\baselineskip % \end{macrocode} % then to set up a new |\strutbox| % \begin{macrocode} \setbox\strutbox\hbox{% \vrule\@height.7\baselineskip \@depth.3\baselineskip \@width\z@}% % \end{macrocode} % We end with a bit of tracing information. % \begin{macrocode} %<*trace> \ifnum \tracingfonts>\tw@ \ifx\f@linespread\@empty \let\reserved@a\@empty \else \def\reserved@a{\f@linespread x}% \fi \@font@info{Changing size to \f@size/\reserved@a \f@baselineskip}% \aftergroup\type@restoreinfo \fi % % \end{macrocode} % When all this is processed |\size@update| redefines itself to % |\relax| so that in later calls of |\selectfont| no extra code % will be executed. % \begin{macrocode} \let\size@update\relax}% } % \end{macrocode} % Instead of defining this macro internally we might speed things % up by placing the code into a separate macro and use |\let|! % \end{macro} % % % \begin{macro}{\size@update} % Normally this macro does nothing; it will be redefined by % |\set@fontsize| to initiate an update. % \begin{macrocode} \let\size@update\relax % \end{macrocode} % \end{macro} % % % \begin{macro}{\type@restoreinfo} % This macro produces some info when a font size and/or baseline % change will get restored. % \changes{1.0r}{1990/08/27}{Some extra tracing info.} % \begin{macrocode} %<*trace> \def\type@restoreinfo{% \ifx\f@linespread\@empty \let\reserved@a\@empty \else \def\reserved@a{\f@linespread x}% \fi \@font@info{Restoring size to \f@size/\reserved@a\f@baselineskip}} % % \end{macrocode} % \end{macro} % % \begin{macro}{\glb@settings} % \begin{macro}{\glb@currsize} % \changes{v2.3a}{1994/01/17}{New math font setup} % \changes{v2.3k}{1994/11/06}{New implementation} % The macro |\glb@settings| globally selects % all math fonts for the current size if necessary. % \begin{macrocode} \def\glb@settings{% % \end{macrocode} % When |\glb@settings| gains control a size % change was requested and all previous font assignments need to % be replaced. % Therefore the old values of the fonts are no longer needed. % For every {\em math group\/} the new assignments are appended to % |\math@fonts|. % But this happens only if the |math@fonts| switch % is set to true. % However, we always set up the correct math sizes for script and % scriptscript fonts since they may be needed even if we don't set % up the whole math machinery. % % Here we set the math size, script size and scriptscript size. % If the |S@|\ldots{} macro is not defined we have to first % calculate the three sizes. % \begin{macrocode} \expandafter\ifx\csname S@\f@size\endcsname\relax \calculate@math@sizes \fi % \end{macrocode} % The effect of this is that |\calculate@math@sizes| % may or may not define the |S@|\ldots{} macro. In the % first case the next time the same size is requested % this macro is used, otherwise |\calculate@math@sizes| is % called again. % This also sets the |math@fonts| switch. % If it is true we must switch the math fonts. % \begin{macrocode} \csname S@\f@size\endcsname \ifmath@fonts %<*trace> \ifnum \tracingfonts>\tw@ \@font@info{Setting up math fonts for \f@size/\f@baselineskip}\fi % % \end{macrocode} % Inside a group we execute the macro for the current math {\em % version}. This sets |\math@fonts| to a list of % |\textfont|\dots{} assignments. |\getanddefine@fonts| (which may % be called at this point) needs the |\escapechar| parameter to be % set to $-1$. % \begin{macrocode} \begingroup \escapechar\m@ne \csname mv@\math@version \endcsname % \end{macrocode} % Then we set |\globaldefs| to 1 so that all following changes are % done globally. The math font assignments recorded in % |\math@fonts| are executed and |\glb@currsize| is set equal to % |\f@size|. This signals that the fonts for math in this size are % set up. % \begin{macrocode} \globaldefs\@ne \math@fonts \let \glb@currsize \f@size \endgroup % \end{macrocode} % Finally we execute any code that is supposed to happen % whenever the math font setup changes. This register will % be executed in local mode which means that everything that is % supposed to have any effect should be done globally inside. % We can't execute it within |\globaldefs\@ne| as we don't know % what ends up inside this register, e.g., it might contain % calculations which use some local registers to calculate the % final (global) value. % \begin{macrocode} \the\every@math@size % \end{macrocode} % Otherwise we announce that the math fonts are not set up for this % size. % \begin{macrocode} %<*trace> \else \ifnum \tracingfonts>\tw@ \@font@info{No math setup for \f@size/\f@baselineskip}\fi % \fi } % % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\baselinestretch} % \changes{v1.0o}{1990/06/24}{Moved to tracefnt.dtx.} % In |\selectfont| we used |\baselinestretch| as % a factor when assigning a value to |\baselineskip|. % We use 1 as a default (i.e.\ no stretch). % \begin{macrocode} %<*2ekernel> \def\baselinestretch{1} % \end{macrocode} % \end{macro} % % \begin{macro}{\every@math@size} % \changes{v1.0u fam.dtx}{1989/12/05}{Hook \cs{every@size} added.} % \changes{v23.k}{1994/10/23}{Renamed to \cs{every@math@size}} % We must still define the hook |\every@math@size| we used in % |\glb@settings|. We initialize it to nothing. It is important to % remember that everything that goes into this hook should to global % updates, local changes will have weird effects. % \begin{macrocode} \newtoks\every@math@size \every@math@size={} % % \end{macrocode} % \end{macro} % % % % \subsection{Math fonts setup} % % % \subsubsection{Outline of algorithm for math font sizes} % % \TeX{} uses the math fonts that are current when the end of a % formula is reached. If we don't want to keep font setups local to % every formula (which would result in an enormous overhead), we have % to be careful not to end up with the wrong setup in case formulas % are nested, e.g., we need to be able to handle % \begin{verbatim} % $ a=b+c \mbox{ \small for all $b$ and $c\in Z$}$ %\end{verbatim} % Here the inner formulae |b| and |c\in Z| are typeset in |\small| but % we have to return to |\normalsize| before we reach the % closing |$| \iffalse$\fi % of the outer formula. % % This is handled in the following way: % \begin{enumerate} % \item At any point in the document the global variable % |\gbl@currsize| contains the point size for which the math fonts % currently are set up. % % \item \label{it:everymath} Whenever we start a formula we compare % its value with the local variable |\f@size| that describes the % current text font size. % % \item If both are the same we assume that we can use the current % math font setup without adjustment. % % \item \label{it:everymathend} If they differ we call |\gbl@settings| % which changes the math font setup and updates |\gbl@currsize|. % \begin{enumerate} % \item If we are recursively inside another formula (|\if@inmath|) we % ensure that |\gbl@settings| is executed again in the outer % formula, so that the old setup is automatically restored. % \item Otherwise, we set the switch |@inmath| locally to |true| so % that all nested formulae will be able to detect that they are % nested in some outer formula. % \end{enumerate} % \end{enumerate} % % % The above algorithm has the following features: % \begin{itemize} % \item For sizes which are not containing any formula no math setup % is done. Compared to the original algorithm of NFSS this results % in the following savings: % \begin{itemize} % \item No unnecessary loading of math fonts for sizes that are not % used to typeset any math formulae (explicit or implicit ones). % \item No time overhead due to unnecessary changes of the math font % setup on entrance and exit of the text font size. % \end{itemize} % % \item Math font setup changes for top-level formulae will survive % (there is no restoration after the formula) thus any following % formula in the same size will be directly typesetable. Compared to % original implementation in NFSS2 % the new algorithm has the overhead of one test per formula % to see if the current math setup is valid (in the original % algorithm the setup was always valid, thus no test was necessary). % % \item In nested formulae the math font setup is restored in the % outer formula by a series of |\aftergroup| commands and checks. % Compared to the original algorithm this involves additional checks % ($2 \times \langle\mbox{non-math levels}\rangle$ per inner % formula). % \end{itemize} % % \subsubsection{Code for math font size setting} % % \begin{macro}{\check@mathfonts} % \changes{v2.3a}{1994/01/17}{New math font setup} % \changes{v2.3c}{1994/01/26}{Correct trace info placement} % In the |\check@mathfonts| macros we implement the steps % \ref{it:everymath} to \ref{it:everymathend} except that instead % of a switch the macro |\init@restore@glb@settings| is used. % \begin{macrocode} %<*2ekernel|package> \def\check@mathfonts{% \ifx \glb@currsize \f@size %<*trace> \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: no change \f@size\space curr/global (\curr@math@size/\glb@currsize)}\fi % \else %<*trace> \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: setting up \f@size\space curr/global (\curr@math@size/\glb@currsize)}\fi % \glb@settings \init@restore@glb@settings \fi \let\curr@math@size\f@size \def\init@restore@glb@settings{\aftergroup\restglb@settings}% } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\init@restore@glb@settings} % \changes{v3.0i}{1996/07/26}{macro added replacing \cs{if@inmath} switch} % This macros does by default nothing but get redefined inside % |\check@mathfonts| to initiate fontsize restoring in nested % formulas. % \begin{macrocode} %<-trace>\let\init@restore@glb@settings\relax %<*trace> \def\init@restore@glb@settings{% \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: no resetting (not in nested math)}\fi } % % \end{macrocode} % \end{macro} % % % \begin{macro}{\restglb@settings} % \changes{v2.3a}{1994/01/17}{New math font setup} % \changes{v2.3c}{1994/01/26}{Correct trace info placement} % This macro will be executed the first time after the current % formula. % \begin{macrocode} \def\restglb@settings{% %<*trace> \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: restoring}\fi % \begingroup \let\f@size\curr@math@size \ifx\glb@currsize \f@size %<*trace> \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: ... already okay (\f@size)}\fi % \else %<*trace> \ifnum \tracingfonts>\thr@@ \@font@info{*** MATH: ... to \f@size}\fi % \glb@settings \fi \endgroup } % \end{macrocode} % \end{macro} % % % \subsubsection{Other code for math} % % % \begin{macro}{\use@mathgroup} % \changes{v1.2b}{1990/01/21}{Macro added to allow cleaner interface.} % \changes{v1.2h}{1990/03/30}{Third argument removed (see % \cs{math@egroup}).} % The |\use@mathgroup| macro should be used in user % macros to select a math group. Depending on whether or not the % \texttt{margid} option is in force it has two or three arguments. % For this reason it should be called as the last macro. % % First we test if we are inside math mode since we don't want to % apply a useless definition. % \changes{v1.1a}{1989/12/16}{Usage of `\quotechar=' macro added.} % \changes{v1.1a}{1989/12/16}{Redefinition of alphabet now simpler.} % \begin{macrocode} \def\use@mathgroup#1#2{\relax\ifmmode % \end{macrocode} % \changes{v1.0o}{1990/06/24}{Tracing code added.} % \changes{v1.0q}{1990/07/07}{Group number added to tracing.} % \begin{macrocode} %<*trace> \ifnum \tracingfonts>\tw@ \count@#2\relax \@font@info{Using \noexpand\mathgroup (\the\count@) #2}\fi % % \end{macrocode} % If so we first call the `=' macro (i.e.\ argument three) to set % up special things for the selected math group. Then we call % |\mathgroup| to select the group given by argument two and % finally we place |#1| (i.e., the argument of the \meta{math % alphabet identifier}) at the end. This part of the code is % surrounded by two commands which behave like |\begingroup| % and |\endgroup| if we want \meta{math alphabet identifier}s % but will expand into |\@empty| if we want simply switches to % a new math group. % \changes{v1.0p}{1990/06/30}{Added \cs{relax} after math group number.} % Since argument number $2$ may be a digit instead of a control % sequence we add a |\relax|. % Otherwise something like |\mit{1}| would switch to math group % $11$ (and back) instead of printing an oldstyle $\mit {1}$. % \changes{v2.0b}{1992/07/26}{} % \begin{macrocode} \math@bgroup \expandafter\ifx\csname M@\f@encoding\endcsname#1\else #1\fi \mathgroup#2\relax % \end{macrocode} % Before we reinsert the swallowed token (arg.\ three) into the % input stream, in the case that the \meta{math alphabet % identifier} isn't called in math mode, we remove the |\fi| % with the |\expandafter| trick. This is necessary if the % token is actually an macro with arguments. In such a case the % |\fi| will be misinterpreted as the first argument which % would be disastrous. % \changes{v1.0f}{1989/12/13} % {\cs{expandafter} added before final \cs{fi}.} % \begin{macrocode} \expandafter\math@egroup\fi}% % \end{macrocode} % The surrounding macros equal |\begingroup| and |\endgroup|. But % using internal names makes it possible to overwrite their meaning % in certain cases. This is for example used in \AmSTeX{} macros % for placing accents. % \end{macro} % % \begin{macro}{\math@egroup} % \changes{v1.0q}{1990/07/07}{Tracing code added.} If the % \texttt{margid} option is in force (which can be tested by % looking at the definition of |\math@bgroup|) we change the % |\math@egroup| command a bit to display the current \meta{math % group number} after it closes the scope of \meta{math alphabet} % with |\endgroup|. % \changes{v3.0h}{1996/05/08}{Use \cs{bgroup} instead of \cs{begingroup} % to match a kernel change made in 1994!!!!} % \begin{macrocode} %<*trace> \ifx\math@bgroup\bgroup \def\math@egroup#1{#1\egroup \ifnum \tracingfonts>\tw@ \@font@info{Restoring \noexpand\mathgroup (\ifnum\mathgroup=\m@ne default\else \the\mathgroup \fi)% }\fi} \fi % % \end{macrocode} % \end{macro} % % \begin{macro}{\getanddefine@fonts} % \changes{v1.0o}{1990/06/24}{\cs{Macro} moved from fam.dtx.} % |\getanddefine@fonts| has two arguments: the \meta{math % group number} and the {\em family/series/shape\/} name as a % control sequence. % \begin{macrocode} \def\getanddefine@fonts#1#2{% % \end{macrocode} % First we turn of tracing when |\tracingfonts| is less than $4$. % \changes{v1.0o}{1990/06/24}{Adding debug code.} % \changes{v1.0r}{1990/08/27} % {Correcting missing name after \cs{tracingon}.} % \begin{macrocode} %<+debug> \pushtracing %<+debug> \ifnum\tracingfonts<4 \tracingoff %<+debug> \else \tracingon\getanddefine@fonts \fi % \end{macrocode} % \changes{v1.0o}{1990/06/24}{\cs{Adding} tracing code.} % \changes{v1.0q}{1990/07/07}{Group number added to tracing.} % \changes{v2.1a}{1992/09/22}{Introduced \cs{tf@size} for math size.} % \begin{macrocode} %<*trace> \ifnum \tracingfonts>\tw@ \count@#1\relax \@font@info{\noexpand\mathgroup (\the\count@) #1 :=\MessageBreak \string#2 \tf@size/\sf@size/\ssf@size}\fi % % \end{macrocode} % We append the current |\tf@size| to |#2| to obtain the font % name.\footnote{One might ask why this expansion does not generate % a macro name that starts with an additional \texttt{\bslash} % character. The solution is that \texttt{\bslash escapechar} is % set to $-1$ before \texttt{\bslash getanddefine@fonts} is % called.} Again, |font@name| is defined globally, for the reasons % explained in the description of |\wrong@fontshape|. % \begin{macrocode} \xdef\font@name{\csname \string#2/\tf@size\endcsname}% % \end{macrocode} % Then we call |\pickup@font| to load it if necessary. % We remember the internal name as |\textfont@name|. % \begin{macrocode} \pickup@font \let\textfont@name\font@name % \end{macrocode} % Same game for |\scriptfont| and |\scriptscriptfont|: % \begin{macrocode} \xdef\font@name{\csname \string#2/\sf@size\endcsname}% \pickup@font \let\scriptfont@name\font@name \xdef\font@name{\csname \string#2/\ssf@size\endcsname}% \pickup@font % \end{macrocode} % Then we append the new |\textfont|\ldots{} assignments to % the |\math@fonts|. % \begin{macrocode} \edef\math@fonts{\math@fonts \textfont#1\textfont@name \scriptfont#1\scriptfont@name \scriptscriptfont#1\font@name}% % \end{macrocode} % Just before ending this macro we have to pop the tracing stack % if it was pushed before. % \begin{macrocode} %<+debug> \poptracing } % % \end{macrocode} % \end{macro} % % % \section{Scaled font extraction} % % \begin{macro}{\ifnot@nil} % We begin with a simple auxiliary macro. It checks % whether its argument is the token |\@nil|. If so, % it expands to |\@gobble| which discards the following % argument, otherwise it expands to |\@firstofone| which % reproduces it argument. % \changes{v2.3n}{1995/05/08}{Use \cs{@firstofone}} % \begin{macrocode} %<*2ekernel> \def\ifnot@nil#1{\def\reserved@a{#1}% \ifx\reserved@a\@nnil \expandafter\@gobble \else \expandafter\@firstofone\fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\remove@to@nnil} % \begin{macro}{\remove@angles} % \begin{macro}{\remove@star} % Three other auxiliary macros will be needed in the following: % |\remove@to@nnil| gobbles up everything up to, and including, % the next |\@nnil| token, and |\remove@angles| and |\remove@star| % do the same % for the character |>| and |*|, respectively, instead of |\@nnil|. % \begin{macrocode} \def\remove@to@nnil#1\@nnil{} \def\remove@angles#1>{\set@simple@size@args} \def\remove@star#1*{#1} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \changes{v3.0c}{1995/08/24}{Macro \cs{gobble@font@spec} removed} % % \begin{macro}{\extract@sizefn} % This macro takes a size specification and parses it into size % function and the optional and mandatory arguments. % \begin{macrocode} \def\extract@sizefn#1*#2\@nil{% \if>#2>\set@size@funct@args#1\@nil \let\sizefn@info\@empty \else\expandafter\set@size@funct@args\remove@star#2\@nil \def\sizefn@info{#1}\fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\try@simple@size} % This function tries to extract the given size (specified by % |\f@size|) for the requested font shape. The font information % must already be present in |\font@info|. % The central macro that does the real work is |\extract@fontinfo|. % We will first give a simple example how this macro works, and % describe it in full generality later. % % Assume that the requested parameters are: {\em encoding scheme\/} % `OT1', {\em family\/} `cm', {\em series\/} `sansserif', % {\em shape\/} `normal', and {\em size\/} `$12$'. % The corresponding font definitions have already been % extracted from the macro |\OT1/cm/sansserif/normal| and % stored in |font@info|. % (Otherwise |\extract@fontinfo| doesn't get called.) % This information consists of a token list made of characters % of category code $12$ of the form % \begin{verbatim} % <10*>cmss10<12*>cmss12<17*>cmss17 %\end{verbatim} % For reasonable packages one usually needs more sizes but this is % sufficient to get the flavour. % We will define a macro |\extract@fontinfo| to find % the external font name (`cmss12') for us: % \begin{verbatim} % \def\extract@fontinfo#1<12*#2>#3<#4\@nnil{% % \set@simple@size@args#3<#4\@nnil % \execute@size@function{#2}} %\end{verbatim} % so that when it gets called via % \begin{verbatim} % \extract@fontinfo<10*>cmss10<12*>cmss12<17*>cmss17\@nnil %\end{verbatim} % |#1| will contain all characters before |<12*>|, % |#2| will be empty, |#3| will be exactly |cmss12|, % and |#3| will be |17>cmss17|. % The expansion is therefore % \begin{verbatim} % \set@simple@size@args cmss12<17*>cmss17\@nnil % \execute@size@function{} %\end{verbatim} % This means: the default (empty) size function will be executed, % with its optional argument set to empty and its mandatory % argument set to |cmss12| by |\set@simple@size@args|. % As we discussed earlier, the effect of the default size function % is to load the given external font (cmss12) at the specified size % (12)---which is exactly what was intended. % % But this is only part of the whole story. % It may be that the size requested does not occur % in the token list |\font@info|. % And the simple definition of |\extract@fontinfo| we gave % above does not allow to specify give more than one % size specification in front of the external font name. % % Let's address these two problems separately. The first one % is solved with the following trick: % We define |\extract@fontinfo| as follows: % \begin{verbatim} % \def\extract@fontinfo#1<12*#2>#3<#4\@nnil{% % \ifnot@nil{#3}% % {\set@simple@size@args#3<#4\@nnil % \execute@size@function{#2}% % }}% %\end{verbatim} % How does this work? % We call |\extract@fontinfo| via % \begin{verbatim} % \expandafter\extract@fontinfo\font@info<12*>\@nil<\@nnil %\end{verbatim} % i.e. by appending |<12*>\@nil<\@nnil|. % If the size (`12' in this case) appears in |\font@info| % everything works as explained above, the only difference being % that argument |#4| of |\extract@fontinfo| % additionally gets the tokens |<12*>\@nil<\@nnil|. % However, if the size is not found everything up to the final % |<12*>| is in argument |#1|, % |#3| gets |\@nil|, % and |#2| and |#4| are empty. % The macro |\ifnot@nil| will discard the calls to % |\set@simple@size@args| and |execute@size@function|, and % hence |\font@info| will continue to be equal to |\@empty|. % This means that no simple size specification matching the % requested size could be found. % % The second problem (more than one simple size specification % for one external font name) will be addressed in % |\set@simple@size@args| below. % % The macros are hidden inside other control sequences % so that we have to build |\extract@fontinfo| in % several steps. % % So here's the actual definition of |\extract@font| in % |\try@simple@size|. % \begin{macrocode} % % this could be replaced by \try@size@range making the subst slower! \def\try@simple@size{% % \end{macrocode} % |\reserved@a| is made an abbreviation for the head of the % definition of the macro |\extract@fontinfo|. % \begin{macrocode} \def\reserved@a{\def\extract@fontinfo####1}% % \end{macrocode} % Now we can define |\extract@fontinfo|. Here we handle a small % but convenient variation: in case of the default (empty) size % function it is allowed to omit the |*| character. % \changes{v2.0b}{1992/07/26}{} % \changes{v2.0c}{1992/09/19}{} % \begin{macrocode} \expandafter\reserved@a\expandafter<\f@size>##2<##3\@nnil{% \ifnot@nil{##2}% {\set@simple@size@args##2<##3\@nnil \execute@size@function\sizefn@info }}% % \end{macrocode} % \changes{v2.0b}{1992/07/26}{} % Now we call |\extract@fontinfo|. Note the |<\@nil| \textsf{tokens} % at the end. % \begin{macrocode} \expandafter\expandafter \expandafter\extract@fontinfo\expandafter\font@info \expandafter<\f@size>\@nil<\@nnil } % \end{macrocode} % \end{macro} % % \begin{macro}{\set@simple@size@args} % As promised above, the macro |\set@simple@size@args| will handle % the case of several size specifications in a row. % If another size specification follows, the very first token of % its argument list is the character |<|. % By starting the definition as follows, % \begin{macrocode} \def\set@simple@size@args#1<{% % \end{macrocode} % parameter |#1| is empty in this case, and contains the size % function's arguments otherwise. We distinguish these two cases % (Note that the character |<| cannot appear in |#1|) by calling % |\remove@angles| for empty |#1| and |\extract@sizefn| % otherwise. In the latter case we have to take care of the % remaining character tokens and discard them. This is done by % |\remove@to@nnil|. Note also the use of Kabelschacht's method. % \begin{macrocode} \if<#1<% \expandafter\remove@angles \else \extract@sizefn#1*\@nil \expandafter\remove@to@nnil \fi} % \end{macrocode} % \end{macro} % % % Now, we are through with the case of a simple size, except for % calling the size function. This will be handled later, as it is % the same mechanism for all types of size specification. We will % now proceed to macros for extraction of size range specification. % % % % \begin{macro}{\extract@rangefontinfo} % |\extract@rangefontinfo| goes through a font shape definition % in the input until it recognizes the tokens |<\@nil->|. % It looks for font ranges with font size functions. It's operation % is rather simple: it discards everything up to the next size % specification and passes this on to |\is@range| for inspection. % The specification (parameter |#2|) is inserted again, in case % it is needed later. % \begin{macrocode} \def\extract@rangefontinfo#1<#2>{% \is@range#2->\@nil#2>} % \end{macrocode} % \end{macro} % % \begin{macro}{\is@range} % |\is@range| is again a sort of dispatcher macro: if the size % specification it is looking at is not a range specification % it discards it and calls |\extract@rangefontinfo| to continue % the search. Otherwise it calls |\check@range| to check the % requested size against the specified range. % % From the way |\is@range| is called inside |\extract@rangefontinfo| % we see that |#2| is the character |>| if the size specification % found is a simple one (that does not contain a |-| character). % This is checked easily enough and |\extract@rangefontinfo| % called again. Note that the extra tokens inserted after the % |\@nil| in the call to |\is@range| appear at the beginning of % the first argument to |\extract@rangefontinfo| and are hence % ignored. % \begin{macrocode} \def\is@range#1-#2\@nil{% \if>#2\expandafter\check@single\else \expandafter\check@range\fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\check@range} % |\check@range| takes lower bound as parameter |#1|, upper bound % as |#2|, size function as |#3| and the size function's arguments % as |#4|. If |#3| is the special token |\@nil| |\font@info| is % exhausted and we can stop searching. % \begin{macrocode} \def\check@range#1-#2>#3<#4\@nnil{% \ifnot@nil{#3}{% % \end{macrocode} % If |#3| wasn't |\@nil| we have a range. We start by assuming that % we have to recurse. Note that we have to reinsert an |<| as it % was already removed by scanning. % \begin{macrocode} \def\reserved@f{\extract@rangefontinfo<#4\@nnil}% % \end{macrocode} % We have to make sure that both boundaries are present, if not we % have to set them. Here we check the upper bound. If |\upper@bound| % is zero after the assignment we set it to |\maxdimen| (upper open % range). We need to use a \meta{dimen} register for the scan since % we may have a decimal number as the boundary. % \begin{macrocode} \upper@bound0#2\p@ \ifdim\upper@bound=\z@ \upper@bound\maxdimen\fi % \end{macrocode} % Now we check the upper boundary against |\f@size|. % If it is larger or equal than |\f@size| this % range is no good and we have to recurse. % \begin{macrocode} \ifdim \f@size \p@<\upper@bound % \end{macrocode} % Otherwise we have to check the lower bound. This time it is not % necessary to scan the boundary value into a register because if % it is empty we get zero as desired. We could even omit the |0| % which would result in |1pt| as default lower boundary. If % |\f@size| is smaller than the boundary we have to recurse. % \begin{macrocode} \lower@bound0#1\p@ \ifdim \f@size \p@<\lower@bound \else % \end{macrocode} % If both tests are passed we can try executing the size function. % \begin{macrocode} \set@simple@size@args#3<#4\@nnil \execute@size@function\sizefn@info % \end{macrocode} % If the function was successful it should have left an external % font name in |\external@font|. We use this to see if we can stop % scanning. Otherwise we recurse. % \begin{macrocode} \ifx\external@font\@empty \else \let\reserved@f\@empty \fi \fi \fi \reserved@f}} % \end{macrocode} % \end{macro} % % \begin{macro}{\lower@bound} % \begin{macro}{\upper@bound} % We use two dimen registers |\lower@bound| and |\upper@bound| % to store the lower and upper endpoints of the range we found. % \begin{macrocode} \newdimen\lower@bound \newdimen\upper@bound % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\check@single} % |\check@single| takes the size as parameter |#1|, size function % as |#2| and the size function's arguments as |#3|. We can assume % that there is always something in the pipeline since the very % last entry is a faked range (see above). % \begin{macrocode} \def\check@single#1>#2<#3\@nnil{% % \end{macrocode} % We start by assuming that % we have to recurse. Note that we have to reinsert an |<| as it % was already removed by scanning. % \begin{macrocode} \def\reserved@f{\extract@rangefontinfo<#3\@nnil}% % \end{macrocode} % Now we check the size against |\f@size|. If it is not equal % |\f@size| it is no good and we have to recurse. % \begin{macrocode} \ifdim \f@size \p@=#1\p@ % \end{macrocode} % Otherwise if this test is passed we can try executing the size % function. % \begin{macrocode} \set@simple@size@args#2<#3\@nnil \execute@size@function\sizefn@info % \end{macrocode} % If the function was successful it should have left an external % font name in |\external@font|. We use this to see if we can stop % scanning. Otherwise we recurse. % \begin{macrocode} \ifx\external@font\@empty \else \let\reserved@f\@empty \fi \fi \reserved@f} % \end{macrocode} % \end{macro} % % % \begin{macro}{\set@size@funct@args} % \begin{macro}{\set@size@funct@args@} % This macro sets the optional and mandatory arguments for a size % function. If the optional argument is not present it is set to % the empty token list. The mandatory argument is delimited by the % token |\@nil|. % \begin{macrocode} \def\set@size@funct@args{\@ifnextchar[% \set@size@funct@args@{\set@size@funct@args@[]}} % \end{macrocode} % % \begin{macrocode} \def\set@size@funct@args@[#1]#2\@nil{% \def\mandatory@arg{#2}% \def\optional@arg{#1}} % % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\DeclareSizeFunction} % This function defines a new size function hiding the internal % from the designer. The body of the size function may use % |\optional@arg| and |\mandatory@arg| denoting the optional and % mandatory argument that may follow the size specification |<...>|. % \changes{v2.1c}{1993/03/18}{Added all args to avoid blanks problems} % \begin{macrocode} %<*2ekernel> \def\DeclareSizeFunction#1#2{\@namedef{s@fct@#1}{#2}} \@onlypreamble\DeclareSizeFunction % % \end{macrocode} % \end{macro} % % % \begin{macro}{\execute@size@function} % This macro is very simple. The only point worth noting % is that calling an undefined size function will do nothing % (actually execute a |\relax|). % \begin{macrocode} %<*2ekernel|package> \def\execute@size@function#1{% %<*trace> \@ifundefined{s@fct@#1}% {\errmessage{Undefined font size function #1}% \s@fct@}% {\csname s@fct@#1\endcsname}% % %<-trace> \csname s@fct@#1\endcsname } % % \end{macrocode} % \end{macro} % % \changes{v2.3j}{1994/05/23}{Removed def of \cs{f@warn@break}} % % % \begin{macro}{\try@size@range} % This macro tries to find a suitable range for requested size % (specified by |\f@size|) in |\font@info|. All the relevant % action is done in |\extract@rangefontinfo|. All that needs % to be done is to stuff in the token list in |\font@info| so % that |\extract@rangefontinfo| can inspect it. % Note the |<-*\@nil><| token at the end to stop scanning. % \changes{v2.0b}{1992/07/26}{} % \begin{macrocode} %<*2ekernel> \def\try@size@range{% \expandafter\extract@rangefontinfo\font@info <-*>\@nil<\@nnil } % \end{macrocode} % \end{macro} % % % \begin{macro}{\try@size@substitution} % \changes{v2.3k}{1994/11/06}{New implementation} % This is the last thing that can be tried. If the desired |\f@size| % is found neither among the simple size specifications nor in one % of the ranges the whole list of size specifications is searched for % a nearby simple size. % \begin{macrocode} \gdef\try@size@substitution{% % \end{macrocode} % First we do some initializations. |\@tempdimb| % will hold the difference between the wanted size and the best % solution found so far, so we initialise it with |\maxdimen|. % The macro |\best@size| will hold the best size found, nothing % found is indicated by the empty value. % \begin{macrocode} \@tempdimb \maxdimen \let \best@size \@empty % \end{macrocode} % Now we loop over the specification % \begin{macrocode} \expandafter \try@simples \font@info <\number\@M>\@nil<\@nnil } % \end{macrocode} % \end{macro} % % % \begin{macro}{\font@submax} % \changes{v2.3d}{1994/04/18}{Changed dimen to macro} % \begin{macro}{\fontsubfuzz} % \changes{v2.3d}{1994/04/18}{Changed dimen to macro} % The macro |\font@submax| records the maximal deviation from the % desired size encountered so far. Its value is used in a warning % message at |\end{document}|. The macro % |\fontsubfuzz| contains the amount that will not cause terminal % warnings (warnings still go into the transcript file). % \begin{macrocode} \def\font@submax{0pt} \def\fontsubfuzz{.4pt} % %<+package>\def\fontsubfuzz{0pt} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\try@simples} % \changes{v2.3k}{1994/11/06}{New implementation} % |\try@simples| goes through a font shape definition % in the input until it recognizes the tokens |<*\@nil><|. % It looks for simple sizes to determine the two closest sizes. % It is assumed that simple sizes are in increasing order. % \begin{macrocode} %<*2ekernel> \gdef\try@simples#1<#2>{% \tryif@simple#2->\tryif@simple} % \end{macrocode} % \end{macro} % % \begin{macro}{\tryis@simple} % \changes{v2.3k}{1994/11/06}{New implementation} % |\tryis@simple| is similar to |\is@range|. If it sees a simple size, % it checks it against the value of |\f@size| and sets % |\lower@font@size| or |\higher@font@size|. In the latter case, it % stops the iteration. By adding |<\number\@M>| at the end of the % line we always have an end point. This is a hack which probably % should be corrected. % % First it checks whether it is finished already, then whether the % size specification in question is a simple one. % \begin{macrocode} \gdef\tryif@simple#1-#2\tryif@simple{% % \end{macrocode} % Most common case for |\reserved@f| first: % \begin{macrocode} \let \reserved@f \try@simples \if>#2% % \end{macrocode} % If so, it compares it to the value of |\f@size|. This is done using % a dimen register since there may be fractional numbers. % \begin{macrocode} \dimen@ #1\p@ \ifdim \dimen@<\@M\p@ % \end{macrocode} % If |\dimen@| is |\@M\p@| we have reached the end of the fontspec % (hopefully) otherwise we compare the value with |\f@size| and % compute in |\@tempdimc| the absolute value of the difference % between the two values. % \begin{macrocode} \ifdim \f@size\p@<\dimen@ \@tempdimc \dimen@ \advance\@tempdimc -\f@size\p@ \else \@tempdimc \f@size\p@ \advance\@tempdimc -\dimen@ \fi % \end{macrocode} % The result is then compared with the smallest difference we have % encountered, if the new value (in |\@tempdimc| is smaller) we % have found a size which is a better approximation so we make it % the |\best@size| and adjust |\@tempdimb|. % \begin{macrocode} \ifdim \@tempdimc<\@tempdimb \@tempdimb \@tempdimc \def \best@size{#1}% \fi % \end{macrocode} % When we have reached the end of the fontspec we substitute the % best size found (if any). We code this inline to save macro % space; in the past this was done by a macro called |\subst@size|. % \begin{macrocode} \else % \end{macrocode} % % % \begin{macro}{\subst@size} % This macro substitutes the size recorded in |\best@size| for % the unavailable size |\f@size|. |\font@submax| records the maximum % difference between desired size and selected size in the % whole run. % \changes{v2.3d}{1994/04/18}{\cs{font@submax} and \cs{fontsubfuzz} % now macros} % \begin{macrocode} % %\subst@size %% coded inline % %\def\subst@size{% \ifx \external@font\@empty \ifx \best@size\@empty \else \ifdim \@tempdimb>\font@submax \relax \xdef \font@submax {\the\@tempdimb}% \fi \let \f@user@size \f@size \let \f@size \best@size \ifdim \@tempdimb>\fontsubfuzz\relax \@font@warning{Font\space shape\space `\curr@fontshape'\space in\space size\space <\f@user@size>\space not\space available\MessageBreak size\space <\f@size>\space substituted}% \fi \try@simple@size \do@subst@correction \fi \fi % %} % \end{macrocode} % \end{macro} % % This brings us back into the main part of |\tryif@simple|. % Finally we get rid of any rubbish left over on the input stack. % % \changes{v3.0c}{1995/08/24}{} % \begin{macrocode} \let \reserved@f \remove@to@nnil \fi \fi % \end{macrocode} % If it's a range iterate also. % \begin{macrocode} \reserved@f} % \end{macrocode} % \end{macro} % % % % \subsection{Sizefunctions} % % In the following we define some useful size functions. % % % \begin{macro}{\s@fct@} % This is the default size function. Mandatory argument is an % external font name, optional argument a scale factor. % The font is scaled % to |\f@size| if no optional argument is present, and to % |\f@size| multiplied by the optional argument otherwise. % \changes{v2.0b}{1992/07/26}{} % \begin{macrocode} \DeclareSizeFunction{}{\empty@sfcnt\@font@warning} \DeclareSizeFunction{s}{\empty@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\empty@sfcnt#1{% \@tempdimb \f@size\p@ \ifx\optional@arg\@empty \else \@tempdimb \optional@arg\@tempdimb #1{Font\space shape\space `\curr@fontshape'\space will\space be\MessageBreak scaled\space to\space size\space \the\@tempdimb}% \fi \edef\external@font{\mandatory@arg\space at\the\@tempdimb}} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\s@fct@gen} % \begin{macro}{\s@fct@sgen} % This size function generates the external name from the mandatory % argument and the requested user size, and thus can be used for % external names where the size is encoded in the font name. The % optional argument a scale factor. The font is scaled to |\f@size| % if no optional argument is present, and to |\f@size| multiplied % by the optional argument otherwise. % \begin{macrocode} \DeclareSizeFunction{gen}{\gen@sfcnt\@font@warning} \DeclareSizeFunction{sgen}{\gen@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\gen@sfcnt{% \edef\mandatory@arg{\mandatory@arg\f@size}% \empty@sfcnt} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\s@fct@genb} % \begin{macro}{\s@fct@sgenb} % This size function is similar to |gen|, but for fonts where the % size is encoded in the font name in centipoints, as in the DC % fonts version 1.2. The font is scaled to |\f@size| % if no optional argument is present, and to |\f@size| multiplied % by the optional argument otherwise. % \begin{macrocode} \DeclareSizeFunction{genb}{\genb@sfcnt\@font@warning} \DeclareSizeFunction{sgenb}{\genb@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\genb@sfcnt{% \edef\mandatory@arg{\mandatory@arg\expandafter\genb@x\f@size..\@@}% \empty@sfcnt} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\genb@x} % \begin{macro}{\genb@y} % The auxiliary macros |\genb@x| and |\genb@y| are used to convert % the |\f@size| into centipoints. % \begin{macrocode} \def\genb@x#1.#2.#3\@@{\two@digits{#1}\genb@y#200\@@} \def\genb@y#1#2#3\@@{#1#2} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\s@fct@sub} % This size function handles font substitution. % The mandatory argument is a family/series/shape combination, % the optional argument (if present) is ignored. The font encoding % scheme cannot be changed. Therefore, the first thing we do is to % prepend the encoding scheme. % \changes{v2.0b}{1992/07/26}{documentation fixes} % \begin{macrocode} \DeclareSizeFunction{sub}{\sub@sfcnt\@font@warning} \DeclareSizeFunction{ssub}{\sub@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\sub@sfcnt#1{% \edef\mandatory@arg{\f@encoding/\mandatory@arg}% % \end{macrocode} % Next action is split the arg into its individual components and % allow for a late font shape load. % \begin{macrocode} \begingroup \expandafter\split@name\mandatory@arg/\@nil \try@load@fontshape \endgroup % \end{macrocode} % Then we record the current |\f@size| since it may get clobbered. % \begin{macrocode} \let\f@user@size\f@size % \end{macrocode} % Then we check whether this new combination is defined and % give an error message if not. In this case we also switch to % |\error@fontshape|. % \begin{macrocode} \expandafter \ifx\csname\mandatory@arg\endcsname\relax \errmessage{No\space declaration\space for\space shape\space \mandatory@arg}% \error@fontshape \else % \end{macrocode} % Otherwise we warn the user about the substitution taking place. % \begin{macrocode} #1{Font\space shape\space `\curr@fontshape'\space in\space size\space <\f@size>\space not\space available\MessageBreak Font\space shape\space `\mandatory@arg'\space tried\space instead}% \expandafter\split@name\mandatory@arg/\@nil \fi % \end{macrocode} % Then we restart the font specification scan by calling % |\get@external@font|. % \begin{macrocode} \edef\f@size{\f@user@size}% \get@external@font % \end{macrocode} % Finally |\do@subst@correction| is called to get the font name % right. % \begin{macrocode} \do@subst@correction } % \end{macrocode} % \end{macro} % % \begin{macro}{\@font@aliasinfo} % \changes{v3.0l}{2019/10/11}{Added 'alias' size function} % Sometimes a substitution is only done to map a long font name to % a standard shape or series, e.g., %\begin{verbatim} %\DeclareFontShape{T1}{Roboto-LF}{b}{it}{<-> alias * Roboto-LF/bold/it}{} %\end{verbatim} % Using the \texttt{ssub} function in that case will give a strange % (and incorrect) warning. As an alternative we therefore offer the % size function \texttt{alias}. It will still add some info into % the \texttt{.log} file, but no longer complains that the font % shape is not available. It is implemented by grabbing the default % warning text and replacing it with a new one. % \begin{macrocode} % %<*2ekernel|latexrelease> %\IncludeInRelease{2020/02/02}% % {\@font@aliasinfo}{alias size function}% \DeclareSizeFunction{alias}{\sub@sfcnt\@font@aliasinfo} \def\@font@aliasinfo#1{% \@font@info{Font\space shape\space `\curr@fontshape'\space aliased\space to\MessageBreak `\mandatory@arg'}% } % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\@font@aliasinfo}{alias size function}% %\let\s@fct@alias\@undefined %\let\@font@aliasinfo\@undefined % %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\s@fct@subf} % The |subf| size function allows substitution of another font. The % mandatory argument is the external name of the font to be % substituted, the optional argument a size scaling factor like % in the default size function. % The main difference to the default size function is the warning % message. % \begin{macrocode} \DeclareSizeFunction{subf}{\subf@sfcnt\@font@warning} \DeclareSizeFunction{ssubf}{\subf@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\subf@sfcnt#1{% #1{Font\space shape\space `\curr@fontshape'\space in\space size\space \f@size\space not\space available\MessageBreak external\space font\space `\mandatory@arg'\space used}% \empty@sfcnt#1% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\s@fct@fixed} % The |fixed| size function is for using a font at a different size % than requested. A warning message is printed, and the external % font to be used is taken from the mandatory argument. % If an optional argument is present it is used as the `at' % size for the font. Otherwise the font is loaded at its design size. % \begin{macrocode} \DeclareSizeFunction{fixed}{\fixed@sfcnt\@font@warning} \DeclareSizeFunction{sfixed}{\fixed@sfcnt\@font@info} % \end{macrocode} % % \begin{macrocode} \def\fixed@sfcnt#1{% \ifx\optional@arg\@empty \let\external@font\mandatory@arg \else \edef\external@font{\mandatory@arg\space at\optional@arg pt}% \fi #1{External\space font\space `\external@font'\space loaded\space for\space size\MessageBreak <\f@size>}% } % % \end{macrocode} % \end{macro} % % \iffalse %<+checkmem>\CHECKMEM % \fi % % % \Finale