我如何计算适合文本所需的行数?

我如何计算适合文本所需的行数?

我想创建一个像这样的命令

\CalcNumber{<the text>}{<width>}{<cs>}

并且存储如果在宽度为的框中排版所需的行数(即\baselineskip四舍五入的高度)。<the text><cs><width>

例如\CalcNumber{A}{\columwith}{\AHeight}\AHeight应该屈服1,而类似的东西\CalcNumber{M M M}{1em}{\MMMHeight}\MMMHeight应该给予某物3

我怎样才能做到这一点?

PS 也欢迎使用 LuaLaTeX 解决方案。

答案1

您可以使用adjustbox将内容装箱在minipage给定宽度内并存储其总高度,然后使用 eTeX 计算基线跳过的因子(最后是discard内容)。

这与使用装箱的其他答案类似,但是是一种更加开箱即用的解决方案(无双关语)。

\documentclass{article}
\usepackage{adjustbox}

\newlength\mycalclength

\newcommand\CalcNumber[3]{%
    \adjustbox{minipage={#2}, gstore totalheight=\mycalclength, discard}{#1}%
    \edef#3{\the\numexpr\dimexpr \mycalclength/\baselineskip\relax\relax}%
}

\begin{document}

\CalcNumber{A}{\columnwidth}{\AHeight}\AHeight

\CalcNumber{M M M M M M M}{1em}{\MMMHeight}\MMMHeight

\end{document}

如果您重新排列参数的顺序并将内容放在最后,则可以使用 的功能\adjustbox将最后一个参数读取为框,而不是参数,从而允许逐字和其他特殊内容。请注意,分配是全局的,因为它发生在组中。

\documentclass{article}
\usepackage{adjustbox}

\newlength\mycalclength

\newcommand\CalcNumber[2]{%
    \adjustbox{minipage={#1}, gstore totalheight=\mycalclength, execute={\gdef#2{\the\numexpr\dimexpr \mycalclength/\baselineskip\relax\relax}}, discard}
}

\begin{document}

\CalcNumber{\columnwidth}{\AHeight}{A}\AHeight

\CalcNumber{1em}{\MMMHeight}{M M M M M M M}\MMMHeight

\end{document}

答案2

有两种方法可以做到这一点:一种是使用\prevgraf,另一种是手动计算线条。

如果您使用 执行此操作\prevgraf,则会为您提供上一段中的行数。这仅在您的输入只有一个段落时才有效。我们所做的是使用 将\setbox0文本放入我们不打印的 vbox 中。在 vbox 中,我们将 设置hsize为您的宽度,即第二个参数,然后将第一个参数打印为段落。我们手动用 结束段落\par,并使用 将\xdef的当前值保存\prevgraf到您作为第三个参数传递的 cs 中。

\def\CalcNumber#1#2#3{%
  \setbox0\vbox{\hsize=#2 \noindent#1\par\xdef#3{\the\prevgraf}}}

如果您的输入超过一个段落,那么您可以使用相同的设置,如下所示:

\makeatletter
\long\def\CalcNumber#1#2#3{%
  \setbox0\vbox{\hsize=#2 \noindent#1}}
\@tempcnta=\dimexpr(\ht0+\dp0)/\baselineskip
\xdef#3{\the\@tempcnta}}
\makeatother

与我们的其他方法类似,我们将文本排版在一个框中。我们需要将我们的定义\CalcNumber\long,以便它可以接受多段文本。然后,我们将框的高度和深度相加,并除以\baselineskip,将其保存在 LaTeX 临时计数寄存器中(这将为我们舍入数字)。然后,我们将其存储在给定的控制序列中,如上所述。

需要注意的是,当您调用宏时,这将使用 baselineskip。您需要考虑字体大小的变化,具体取决于您计划将其用于什么用途。

答案3

值得一提的是,ConTeXt 提供了一个宏\determinenofline{...},用于确定内容的行数(在 中排版时\vbox)。结果存储在计数器中:\noflines

这将计算排版行数(而不是倍数的高度(或LaTeX 中\lineheight所说的)。这里有一个例子来表明:\baselineskipsupp-box.mkiv

\starttext

\determinenoflines{test\\test}
\the\noflines

\determinenoflines{\bfd test\\test}
\the\noflines

\determinenoflines{\definedfont[Sans at 40pt]test\\test}
\the\noflines
\stoptext

所有这三个测试都给出了结果2

要计算特定宽度的内容的行数,只需\hsize为内容设置即可。例如:

\starttext
\vbox{\hsize=3cm \input ward\relax}

\determinenoflines{\hsize=3cm \input ward\relax}
\the\noflines
\stoptext

得出(第一个\vbox只是为了验证结果)。

在此处输入图片描述

答案4

这用来\vsplit计算行数。唯一令人惊讶的是它在开头intemise添加了一个空行(和一些负数)。\vspace

\theNLcount可以通过在宏末尾添加来返回行数。在本例中,我想使用来显示数字\marginpar,并且它使用\marginparwidth默认宽度。

由于您一次只想分割一行,因此最好请求尽可能少,因此为 0pt。

\documentclass{article}
\usepackage{amsmath}
\usepackage{blindtext}

\newcounter{NLcount}

\newcommand{\numberoflines}[2][\linewidth]% #1=width (optional), #2=text
{\bgroup
  \hsize=#1\relax
  \clubpenalty=0
  \widowpenalty=0
  \displaywidowpenalty=0
  \predisplaypenalty=0
  \postdisplaypenalty=0
  \interlinepenalty=0
  \setbox0=\vbox{#2}%
  \setcounter{NLcount}{0}%
  \loop\ifdim\ht0>0pt
    \stepcounter{NLcount}%
    \setbox1=\vsplit0 to 0pt
  \repeat
\egroup}% \theNLcount

\begin{document}

\numberoflines{above \[x=a\] more text \begin{equation} y=b \end{equation} below}

\hrule\leavevmode\marginpar{\theNLcount{} lines}
above \[x=a\] more text \begin{equation} y=b \end{equation} below
\hrule

\numberoflines{above\newline \rule{1in}{1in}\newline below}

\hrule\leavevmode\marginpar{\theNLcount{} lines}
above\newline \rule{1in}{1in}\newline below
\hrule

\numberoflines{\begin{itemize}
  \item One
  \item Two
\end{itemize}}

\hrule\leavevmode\marginpar{\theNLcount{} lines}
\begin{itemize}
  \item One
  \item Two
\end{itemize}
\hrule

\numberoflines{\blindtext}

\hrule\leavevmode\marginpar{\theNLcount{} lines}
\blindtext
\hrule

\numberoflines{\tiny\blindtext}

\hrule\leavevmode\marginpar{\theNLcount{} lines}
{\tiny\blindtext}
\hrule

\newpage
\numberoflines[2in]{\blindtext}
\hrule\noindent\marginpar{\theNLcount{} lines}
\parbox{2in}{\strut\blindtext}
\hrule

\end{document}

相关内容