[Tex/LaTex] Defining a Length that Scales with Fontsize Changes

fontsizelengthsscaling

I noticed a behavior regarding lengths under fonstsize changes, which I'm hoping there is a way to circumvent. Consider this MWE:

\documentclass{article}
\begin{document}

\newlength\mylength
\mylength=\baselineskip
\def\stringmylength{\the\baselineskip}

mylength~~~  baselineskip~~~ stringmylength\\

\the\mylength~~~~~~~~\the\baselineskip~~~~~~~~~~~~~\stringmylength\\

\Large
\the\mylength~~~\the\baselineskip~~~~~~~\stringmylength\\

\end{document}

with this output:

enter image description here

When I define a length in a scalable unit (here, as \baselineskip, though the same behavior occurs if I define \mylength as 2.7871ex), I would hope that, upon changing the fontsize, it would scale. But \mylength does not. I seem to recall reading somewhere that lengths are converted to some internal LaTeX unit, which would explain, perhaps, why a length, once specified, doesn't scale with fontsize.

Yet, it is clear that certain lengths do scale, such as \baselineskip, as given in my example.

Also, I could "work around" the problem by storing the length not as a length, but as a string (\stringmylength in my example), though that seems crass to me.

Is there a way to define a LaTeX length which will scale with fontsize changes?

If not, what is the prescribed way of manually modifying lengths to conform to fontsize changes?

[EDIT: As mentioned in a comment to David, and picked up on by egreg, this question concerns the formulation of lengths in the stackengine package]

Best Answer

Recommending, in your package documentation, a syntax such as \Sstackgap=0.7ex is disputable; the standard LaTeX syntax uses \setlength and since \Sstackgap is a skip register (since you define it with \newlength), this opens the way to weird errors; a user typing

\Sstackgap=0.3ex Plus other things

will be puzzled with a strange error message Missing number treated as 0. Do you see why?

If you want this length to be expressed in the font based units em or ex, respecting the current font, you must treat it as a macro:

\newcommand{\setstackgap}[2]{%
  \@namedef{#1stackgap}{#2}%
}

where #1 is either L or S (add an error checking routine). Then you can say

\newcommand\stackgap{%
  \@nameuse{\if S\stacktype S\else L\fi stackgap}\relax
}

and the user can say

\setstackgap{S}{.7ex}
\setstackgap{L}{.3em}

or whatever. Alternatively, define a \stackengineset macro:

\newcommand{\stackengineset}[2]{\def#1{#2}}

so users can type

\stackengineset{\Sstackgap}{0.7ex}

Note that in both ways a fixed length can be specified as well.


You could use a syntax such as \Sstackgap=0.7ex, by doing

\def\Sstackgap{\afterassignment\@foo\skip@}
\def\@foo{\edef\@Sstackgap{\the\skip@}}

and modifying \stackgap to use \@Sstackgap instead of \the\Sstackgap; similarly for \Lstackgap. But I can't recommend this way of doing things, contrary to the standard LaTeX syntax.