\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}
举一个“正面”的例子来说明我为什么使用 \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}
答案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}