7

I need to find depth of a string, for this end i would like to loop over the string and ask for depth of every character.

I ask for depth like this:

\dimen=\fontchardp\expandafter\font`\a

And loop like this:

\def\mystring{abcdefgh}
\StrLen{\mystring}[\len]
\newcount\X \X=\len

\loop
\StrMid{\mystring}{\X}{\X}\par    
\advance \X by -1
\unless\ifnum \X<1
\repeat

But this doesn't work, even though i tried with different combinations of \expandafter:

\dimen=\fontchardp\font`\StrMid{\mystring}{\X}{\X}

If there are easier ways to get depth of a string i would appreciate it, but also i would like to know how to make previous line of code work. Thanks.

  • Using \StrChar is simpler, isn't it? – egreg Apr 25 '17 at 9:50
  • @egreg probably i need start with reading docs not programming:) – Yola Apr 25 '17 at 11:28
  • If ligatures are involved, then the depth of the ligature can be different than the maximum depth of the characters that are used to build the ligature. – Heiko Oberdiek Aug 6 '17 at 14:23
11

The answer by marsupilam covers how one would normally achieve the task: typeset the content and get the box depth.

There are two issues with the code you've got. First, the TeX primitive \dimen has to be followed by a register number, not by an =. Using the fact that \dimen0 is a scratch register in LaTeX, you therefore can use \dimen0=<some valid dimension>. The second is that \StrMid doesn't generate a letter per se (it's not 'expandable'), it is instructions to do that in a typesetting context. However, there is an optional argument that will 'return' what you want

\StrMid{\mystring}{\X}{\X}[\tmp] % \tmp now expands to the substring

We can use that with \expandafter to get what \fontchardp requires: the character number you are interested in

\documentclass{article}
\usepackage{xstring}

\begin{document}

\def\mystring{abcdefgh}
\StrLen{\mystring}[\len]
\newcount\X
\X=\len

\loop
  \StrMid{\mystring}{\X}{\X}[\tmp]
  \dimen0=\fontchardp\expandafter\font\expandafter`\tmp
  \edef\x{\tmp\space\the\dimen0 }%
  \show\x
  \advance \X by -1 %
  \unless\ifnum \X<1 %
\repeat

\end{document}

(I've show rather than typeset the result)

  • Really appreciate this! – Yola Apr 25 '17 at 8:53
11

I don't know about your approach using a loop, but to get the depth, just use \settodepth

See : https://tex.stackexchange.com/a/37294/116936

You can also use the calc package \depthof

\documentclass{article}

\begin{document}
\def\mystring{abcdefgh}
\newlength\myLength

\settodepth{\myLength}{\mystring}

\the\myLength
\end{document}

Cheers,

  • +1, could you please also provide a solution for the line of code which doesn't work in the post? I think there is an important concept behind it. – Yola Apr 25 '17 at 8:19
4

Similar to Joseph’s, but using less code

\documentclass{article}
\usepackage{xstring}

\newcount\X
\newdimen\stringdepth

\begin{document}

\def\mystring{abcdefgh}
\StrLen{\mystring}[\len]

\X=0
\stringdepth=0pt

\loop
  \ifnum\len>\X
  \advance\X by 1
  \StrChar{\mystring}{\X}[\tmp]%
  \begingroup\edef\x{\endgroup
    \dimen0=\fontchardp\font`\tmp\relax
  }\x
  \ifdim\dimen0>\stringdepth \stringdepth=\dimen0 \fi
  % just for showing the work
  \typeout{\tmp\space has depth \the\dimen0 }%
\repeat

\typeout{Max depth: \the\stringdepth}

\end{document}

Of course

\settodepth{\stringdepth}{\mystring}

is much more efficient.

A different loop, quite flexible, as shown by the examples: the current item is referred to as #1 in the final argument to \stringloop:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\stringloop}{smm}
 {
  \IfBooleanTF{#1}
   { % we have a macro as argument
    \tl_map_inline:Nn #2 { #3 }
   }
   { % an explicit token list
    \tl_map_inline:nn { #2 } { #3 }
   }
 }
\ExplSyntaxOff

\newdimen\stringdepth

\begin{document}

\def\mystring{abcdefgh}

\stringloop{abcdefgh}{\typeout{#1 has depth \the\fontchardp\font`#1}}

\stringdepth=0pt
\stringloop*{\mystring}{%
  \ifdim\fontchardp\font`#1>\stringdepth
    \stringdepth=\fontchardp\font`#1\relax
  \fi
}
\typeout{Max depth in \mystring: \the\stringdepth}

\end{document}

Here is the output on the terminal (and log file):

a has depth 0.0pt
b has depth 0.0pt
c has depth 0.0pt
d has depth 0.0pt
e has depth 0.0pt
f has depth 0.0pt
g has depth 1.94444pt
h has depth 0.0pt
Max depth in abcdefgh: 1.94444pt
  • As you might guess, for my answer I was sticking close to the OP's code to make it illustrative. – Joseph Wright Apr 25 '17 at 10:37
  • @JosephWright That's why I upvoted your answer! – egreg Apr 25 '17 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.