如何避免 \vbox\unvbox 导致 \vbox 扩大?

如何避免 \vbox\unvbox 导致 \vbox 扩大?

\vbox{\unvbox ...} 操作应删除过时的垂直空间。在以下情况下,结果框内的某处会出现额外的垂直空间。结果 \vbox 的总高度从 45.0pt 增加到 46.94444pt。

我尝试了 \baselineskip、\lineskip 等,但找不到避免扩大的方法。在我的应用程序中,至关重要的是,生成的框永远不会大于 \vsplit 操作中给出的尺寸。

\documentclass{article}

\begin{document}

\newbox\mybox
\setbox\mybox=\vbox%
{%
  Bla 1
  \begin{itemize}
  \item bla
  \item bla
  \end{itemize}
  Bla 2.
  \begin{itemize}
  \item bla
  \item bla
  \end{itemize}
}

\splittopskip=0pt%
\splitmaxdepth=0pt%
\setbox\mybox=\vsplit\mybox to 45pt%

Before \verb+\vbox\unvbox+ :

{\fboxsep0pt\fbox{\copy\mybox}}\par
\edef\myboxheight{\the\dimexpr\ht\mybox+\dp\mybox\relax}%
Total height: \myboxheight

\bigskip

After \verb+\vbox\unvbox+ :

\setbox\mybox=\vbox{\unvbox\mybox}

{\fboxsep0pt\fbox{\copy\mybox}}\par
\edef\myboxheight{\the\dimexpr\ht\mybox+\dp\mybox\relax}%
Total height: \myboxheight

\end{document}

示例 1

举一个“正面”的例子来说明我为什么使用 \unvbox,请参见以下内容。这里,拆分会产生大量空间,这些空间可以通过拆箱和再次装箱来消除。

\documentclass{article}
\usepackage{amsmath}

\begin{document}

\newbox\mybox
\setbox\mybox=\vbox%
{%
\begin{enumerate}
\item
$\!
\begin{aligned}[t]
-2x &>4\\
x   &< \frac{4}{-2} \\
x       &< -2
\end{aligned}
$
\item
$\!
\begin{aligned}[t]
7x -1   &< 13\\
7x      &< 13 +1\\
7x      &< 14\\
x           &< \frac{14}{7}\\
x       &< 2
\end{aligned}
$
\end{enumerate}}

\splittopskip=0pt%
\splitmaxdepth=0pt%
\setbox\mybox=\vsplit\mybox to 90pt%

{\fboxsep0pt\fbox{\copy\mybox}}

\setbox\mybox=\vbox{\unvbox\mybox}

{\fboxsep0pt\fbox{\copy\mybox}}\par
\edef\myboxheight{\the\dimexpr\ht\mybox+\dp\mybox\relax}%

\end{document}

示例 2

答案1

\vsplit\mybox to 45pt箱子强制到总高度后45pt

\showboxdepth=\maxdimen
\showboxbreadth=\maxdimen
\showbox\mybox

.log文件显示:

> \box26=
\vbox(45.0+0.0)x345.0, glue set - 0.32408
.\hbox(6.94444+0.0)x345.0, glue set 306.8055fil
..\hbox(0.0+0.0)x15.0
..\OT1/cmr/m/n/10 B
..\OT1/cmr/m/n/10 l
..\OT1/cmr/m/n/10 a
..\glue 3.33333 plus 1.66666 minus 1.11111
..\OT1/cmr/m/n/10 1
..\penalty 10000
..\glue(\parfillskip) 0.0 plus 1.0fil
..\glue(\rightskip) 0.0
.\penalty -51
.\glue 8.0 plus 3.0 minus 4.0
.\glue -8.0 plus -3.0 minus -4.0
.\glue 4.0 plus 1.0 minus 3.0
.\glue(\parskip) 4.0 plus 2.0 minus 1.0
.\glue(\baselineskip) 5.05556
[...]

最外层的盒子没有设置其自然高度,其粘合部分(可收缩部分)减少了因子- 0.32408。可收缩部分的总和(minus\glue文件行之后.log)为6pt。乘以0.32408结果是1.9248。这就是与第二种情况的不同(模数舍入问题)。

后一种情况下,之后\vbox{\unvbox\mybox}盒子内容是一样的,不同之处在于最上面的胶水设置\vbox

> \box26=
\vbox(46.94444+0.0)x345.0

此处设置了框的自然宽度,比45pt强制第一种情况略大。不需要组件的plus和部分。minus\glue

可以使用以下方法强制设置高度\vbox to

\setbox\mybox=\vbox to 45pt{\unvbox\mybox}

但我不明白这个练习的意义。你想实现什么? \vbox+\unvbox不会删除“过时的垂直空间”。而且,在你的情况下,开头和结尾没有垂直空间会产生影响。垂直框以 开始和结束\hbox

第二个例子

第二个示例也没有删除任何空白元素(glue、kern)。开头减少空白的效果也是不同glue设置的效果。盒子被强制为高度为的盒子。90pt盒子的自然高度是18.39996pt。因此,可拉伸组件被使用,并被放大了巨大的倍数6.77441

\unskip有时,可以使用和来删除框末尾的空白。但是,如果后面有不可见的内容(例如或 )\unkern,则此方法无效。而且此技巧不适用于垂直框的第一部分。只有 LuaTeX 允许对框进行全面检查和修改。\special\write

如果垂直框包含粘连,则其高度可以设置为不同于其自然高度。然而,这双向起作用,框的高度可以变小或变大。因此,相反的过程,将框再次设置为其自然高度会使框变小或变大。

答案2

我感谢所有给出的答案和解释。它们让真正发生的事情变得清晰起来。现在,我试着自己回答——希望不要太愚蠢。

在下面的代码中,\vbox+\unvbox操作被宏 所取代。它使用+\rebox重置粘合,但强制结果框的高度不超过限制(从分割中获取)。\vbox\unvbox

现在,示例 1 保持在 45.0pt,而示例 2 可以减少上面的可见空间。

\documentclass{article}
\usepackage{amsmath}

\def\rebox#1#2{%
  \setbox#2=\vbox{\unvbox#2}%
  \ifdim\dimexpr\ht#2+\dp#2>#1%
    \setbox#2=\vbox to \the\dimexpr#1-\dp#2\relax{\unvbox#2}%
  \fi%
}

\def\testmybox#1{%
  \par%
  {\fboxsep0pt\fbox{\copy#1}}\par%
  \edef\myboxheight{\the\dimexpr\ht#1+\dp#1\relax}%
  Total height: \myboxheight%
}

\begin{document}

\newbox\mybox
\setbox\mybox=\vbox%
{%
  Bla 1
  \begin{itemize}
  \item bla
  \item bla
  \end{itemize}
  Bla 2.
  \begin{itemize}
  \item bla
  \item bla
  \end{itemize}
}

\splittopskip=0pt%
\splitmaxdepth=0pt%
\setbox\mybox=\vsplit\mybox to 45pt%

\textbf{Example 1:}

Before \verb+\rebox+ :

{\fboxsep0pt\fbox{\copy\mybox}}\par
\edef\myboxheight{\the\dimexpr\ht\mybox+\dp\mybox\relax}%
Total height: \myboxheight

\bigskip

After \verb+\rebox+ :

\rebox{45pt}{\mybox}
\testmybox{\mybox}

\setbox\mybox=\vbox%
{%
\begin{enumerate}
\item
$\!
\begin{aligned}[t]
-2x &>4\\
x   &< \frac{4}{-2} \\
x       &< -2
\end{aligned}
$
\item
$\!
\begin{aligned}[t]
7x -1   &< 13\\
7x      &< 13 +1\\
7x      &< 14\\
x           &< \frac{14}{7}\\
x       &< 2
\end{aligned}
$
\end{enumerate}}

\bigskip

\splittopskip=0pt%
\splitmaxdepth=0pt%
\setbox\mybox=\vsplit\mybox to 90pt

\textbf{Example 2:}

Before \verb+\rebox+ :

{\fboxsep0pt\fbox{\copy\mybox}}\par
\edef\myboxheight{\the\dimexpr\ht\mybox+\dp\mybox\relax}%
Total height: \myboxheight

\bigskip

After \verb+\rebox+ :

\rebox{90pt}{\mybox}
\testmybox{\mybox}

\end{document}

答案已编译

相关内容