我\vbox
在文档的不同部分排版了两行,我打算将它们附加到一起,就好像它们的所有内容都只在一个 中排版一次一样\vbox
。因此,从一个\vbox
es 内容到另一个 es 内容,行距保持不变,等等。有没有一种干净的方法来执行这样的附加?
我当前的技术导致第一行最后一行\vbox
和第二行第一行基线之间的空间不足\vbox
。理想情况下,我希望有一个通用解决方案,可以用于附加任何两个\vbox
es,并且结果表现得就像最后一个框的所有内容都在一个 中排版一次一样\vbox
。推论:现在假设两个框在独立排版时行距相同;推论是,第一个框的最后一行和第二个框的第一行之间的行距可以等于第一个框中使用的行距(假设第二个框在文档中排版时具有不同的行距)。
检查此屏幕截图中的行距问题,以及其后的完整代码示例:
代码:
% file: vboxappend.tex
% >> lualatex vboxappend.tex
\documentclass[notitlepage,letterpaper]{article}
%NOTE: Uncomment the following line, and run with lualatex if you want to visualize debug markers
%\usepackage{lua-visual-debug}
\usepackage{geometry}
\usepackage[expansion=alltext,shrink=20,stretch=20]{microtype}
\usepackage{fontspec}
\usepackage{blindtext}
\geometry{left=2in,right=2in,top=1in,bottom=1in}
\setmainfont{Verdana}
\begin{document}
% First page without using vboxes
\thispagestyle{empty}
\newcommand{\mytesttext}{\blindtext[1]}
\mytesttext\par
\mytesttext
% Second page using vboxes
\newpage
\thispagestyle{empty}
\newbox\myvboxone
\setbox\myvboxone=\vbox{{\hsize=\textwidth \mytesttext \endgraf}}%
\newbox\myvboxtwo
\setbox\myvboxtwo=\vbox{{\hsize=\textwidth \mytesttext \endgraf}}%
\newbox\myvboxthree
\setbox\myvboxthree=\vbox{{\hsize=\textwidth \unvbox\myvboxone\unvbox\myvboxtwo \endgraf}}%
\box\myvboxthree
\end{document}
答案1
当垂直材料被\unvbox
编辑时,结果不尊重这种材料上方和下方的基线跳过。如果我们需要在这种材料下方添加一些东西,那么\lastbox
可以使用技巧。这会从\unvbox
编辑材料中删除最后一个框并将其再次返回到垂直列表,但\prevdepth
设置正确,下一个“正常”行将尊重基线跳过设置。但是你没有下一个“正常”行,你有下一个\ubvbox
编辑材料。所以新问题来了。这可以通过\null
(即\hbox{}
)解决。代码应该是:
\newbox\myvboxone
\setbox\myvboxone=\vbox{{\mytesttext \endgraf}}%
\newbox\myvboxtwo
\setbox\myvboxtwo=\vbox{{\null \mytesttext \endgraf}}%
\newbox\myvboxthree
\setbox\myvboxthree=\vbox
{{\unvbox\myvboxone \lastbox\kern-\prevdepth \unvbox\myvboxtwo}}%
\box\myvboxthree
\bye
请注意,\myvboxone
与您的 相同。当 时,\unvboxed
使用\lastbox
技巧,然后\kern-\prevdepth
。现在,我们正好位于最后一行的基线。下一个\unvboxed
材料从 开始,\null
定位到 的最后一行的基线\myvboxone
。下一行是正确的,因为它是在创建\baselineskip
时计算的。\myvboxtwo
编辑如果您想使用\vboxes
来自\vsplit
,那么核心技巧是将设置\splittopskip
为,首先在文本列之前\baselineskip
插入,然后在此执行第一个“虚拟” 。这会在列中的第一行上方插入正确的行跳过。接下来也在列的其余部分上方插入正确的行跳过。因此,您可以确保来自的材料的行为就像这里的一样(但它不在这里:)。现在将拆分的部分重新连接在一起只需要这个技巧。示例:\penalty0
\vsplit
\penalty0
\vsplits
\vplit
\null
\lastbox
\newbox\myvboxone
\newbox\myvboxtwo
\newbox\myvboxthree
\newbox\allcolumn
\setbox\myvboxone=\vbox{{\mytesttext \endgraf}}% begin of the text
\splittopskip=\baselineskip % << core trick is here + \penaty0
\setbox\allcolumn=\vbox{{\penalty0 \mytesttext \endgraf}}
\setbox0=\vsplit\allcolumn to0pt % this resets \allcolun, now it starts with
% correct skip above the first line.
\setbox\myvboxtwo=\vsplit\allcolumn to3\baselineskip % three lines from \allcolumn
\setbox\myvboxthree=\vbox % cat begin of the text with three lines from \allcolumn
{\unvbox\myvboxone \lastbox\kern-\prevdepth \unvbox\myvboxtwo}%
\bigskip test1:\medskip \copy\myvboxthree % testing of the result
\setbox\myvboxtwo=\vsplit\allcolumn to4\baselineskip % next 4 lines from \allcolumn
\setbox\myvboxthree=\vbox % cat previous text with next four lines
{\unvbox\myvboxthree \lastbox\kern-\prevdepth \unvbox\myvboxtwo}%
\bigskip test2:\medskip \box\myvboxthree % testing of the result
\bye
答案2
将其放在\strut
第一个 vbox 中的文本末尾,并放在第二个 vbox 中的文本开头。
该解决方案有效。我最初的解释是错误的,因为我误读\unvbox
为\box
:(错误的)解释是,当 TeX 将每个框堆叠在“垂直列表”中时,每个框都被视为单个大字母;TeX 不会查看框内部以查看内部文本的基线在哪里,也不会尝试使它们有规律地间隔开。
没有基线跳跃的真正解释是这是 的一个特性\unvbox
。但\strut
仍能完成工作。
我假设您实际上正在做一些需要\vbox
...的\parbox
事情。在一般情况下可能更好。如果您只是想防止分页符,那么有更好的解决方案(包括\samepage
,只要您知道它仅适用于段落中的行,它就非常有效)。
还有更奇特的事情可能,将盒子内容重新装箱,并\vtop
测量\vbox
第一行和最后一行的高度和深度,然后设置\prevdepth
TeX 根据内容执行垂直间距,即使没有支柱。
答案3
正如 egreg 所解释的那样这个答案:
在 的开头
\vbox
,参数\prevdepth
设置为-1000pt
,当您执行 时\unvbox
,该值会抑制行间粘合。
在您的例子中,\prevdepth
被设置-1000pt
为 之后,除其他外,这会导致您提到的被编辑\setbox\myvboxtwo=\vbox{
时的问题。如果您在设置 的深度后 保存的深度并将其作为值插入到 的赋值开头,则被编辑之后的行间粘连将是正确的。\myvboxtwo
\unvbox
\myvboxone
\prevdepth
\myvboxtwo
\myvboxtwo
\unvbox
\myvboxone
注意:我把你的代码改用 LaTeX 的,\newsavebox
而不是 TeX 的\newbox
。据我所知,它进行更多检查。另外,在您分配给 期间\myvboxthree
,TeX 永远不会切换到水平模式,因此\hsize
设置 和\endgraf
是无用的。
\documentclass{article}
\usepackage[expansion=alltext,shrink=20,stretch=20]{microtype}
\usepackage{fontspec}
\usepackage{blindtext}
\setmainfont{Verdana}
\newcommand{\mytesttext}{\blindtext[1]}
\newdimen\mydim
\pagestyle{empty}
\newsavebox{\myvboxone}
\newsavebox{\myvboxtwo}
\newsavebox{\myvboxthree}
\begin{document}
\setbox\myvboxone=\vbox{{\hsize=\textwidth \mytesttext \endgraf}}
\mydim=\dp\myvboxone
\setbox\myvboxtwo=\vbox{
\prevdepth=\mydim
{\hsize=\textwidth \mytesttext \endgraf}
}
\setbox\myvboxthree=\vbox{
\unvbox\myvboxone
\unvbox\myvboxtwo
}
\box\myvboxthree
\end{document}
如果我们在的最后一行添加一个非常深的框或规则\myvboxone
,如下所示:
\setbox\myvboxone=\vbox{
{\hsize=\textwidth \mytesttext
\vrule width 0.4pt depth 20pt\endgraf}}
上述解决方案充分考虑了它的深度(请注意,我没有再次显示第一个框的开始和第二个框的结束:它们与上面的相同):
4月13日 编辑
回复此评论:如果我使用以下修改后的定义\mytesttext
:
\newcommand{\mytesttext}{\blindtext[1]ee eeeeeee eee eee ee eee eee ee eee ee
eee ee eeeeeee eee eee ee eeen}
然后两个\vbox
es 连接处的放大输出如下:
我觉得这条内线看起来不错。