How can I calculate a number of lines needed to fit the text?
There are two ways that you can do this: one is with \prevgraf
, and the other by calculating the lines manually.
If you do it with \prevgraf
, that gives you the amount of lines in the previous paragraph. This will only work if your input is meant to be only one paragraph. What we do is we use \setbox0
to put the text into a vbox which we don't print. In the vbox, we set the hsize
to your width, the second argument, and then print the first argument as a paragraph. We manually end the paragraph with \par
, and the use \xdef
to save the current value of \prevgraf
into the cs you passed as the third argument.
\def\CalcNumber#1#2#3{%
\setbox0\vbox{\hsize=#2 \noindent#1\par\xdef#3{\the\prevgraf}}}
If your input is more than one paragraph, then you can use the same setup as follows:
\makeatletter
\long\def\CalcNumber#1#2#3{%
\setbox0\vbox{\hsize=#2 \noindent#1}}
\@tempcnta=\dimexpr(\ht0+\dp0)/\baselineskip
\xdef#3{\the\@tempcnta}}
\makeatother
In a similar fashion to our other approach, we typeset our text in a box. We need to define our \CalcNumber
as \long
, so it can accept text of more than one paragraph. Then, we add the height and depth of the box, and divide by \baselineskip
, saving it in a LaTeX temporary count register (this will round the number for us). We then store this in our give control sequence, as above.
A caveat here is that this will use whatever the baselineskip is when you call the macro. You'd need to account for variations in font sizes, depending on what you plan on using this for.
FWIW, ConTeXt provides a macro \determinenofline{...}
that determines the number of lines of the content (when typeset in a \vbox
). The result is stored in the counter: \noflines
.
This counts the number of typeset lines (not the height in the multiple of \lineheight
(or what is called \baselineskip
in LaTeX). Here is one example from supp-box.mkiv
to show that:
\starttext
\determinenoflines{test\\test}
\the\noflines
\determinenoflines{\bfd test\\test}
\the\noflines
\determinenoflines{\definedfont[Sans at 40pt]test\\test}
\the\noflines
\stoptext
All three of these tests give 2
.
To count the number of lines for a content of a specific width, you can simply set \hsize
for the content. For example:
\starttext
\vbox{\hsize=3cm \input ward\relax}
\determinenoflines{\hsize=3cm \input ward\relax}
\the\noflines
\stoptext
which gives (the first \vbox
is just to verify the result).
This is an attempt based on the lineno
package.
\documentclass{article}
\usepackage[running]{lineno}
\usepackage{lipsum}
\newcounter{mylines}
\newsavebox{\marmot}
\newcommand{\CalcNumber}[3]{
\savebox{\marmot}{\begin{minipage}{#2}\linenumbers*
\begin{internallinenumbers}
#1 \par
\setcounter{mylines}{\thelinenumber}\addtocounter{mylines}{-1}
\end{internallinenumbers}
\end{minipage}}
\let#3=\themylines}
\begin{document}
\CalcNumber{\lipsum[1]}{8cm}{\myx}
\myx
\CalcNumber{A}{8cm}{\myy}
\myy
\end{document}