![排版一个垂直框,将垂直框第一行的基线作为其顶部锚点](https://linux22.com/image/311660/%E6%8E%92%E7%89%88%E4%B8%80%E4%B8%AA%E5%9E%82%E7%9B%B4%E6%A1%86%EF%BC%8C%E5%B0%86%E5%9E%82%E7%9B%B4%E6%A1%86%E7%AC%AC%E4%B8%80%E8%A1%8C%E7%9A%84%E5%9F%BA%E7%BA%BF%E4%BD%9C%E4%B8%BA%E5%85%B6%E9%A1%B6%E9%83%A8%E9%94%9A%E7%82%B9.png)
介绍
由于我的实际用例显然比 MWE 中提出的问题要复杂一些,因此我将首先解释用例,以便您判断我的方法是否正确。也许可以使用替代方法来获得所需的输出。
就我的情况而言,问题与间距有关。更具体地说,我试图对齐两个基线。简而言之,问题是:
- 我需要处于
\vskip
两种高度之间。 - 执行此操作时,排版的框会向下移动。在我看来,这是不可取的:
\marginpar
框内容第一行的基线应位于我们刚刚对齐的基线上\vskip
。其余部分应向下排版。
从第 2 点来看,我最初的(可能的)解决方法是将 marginpar 框的高度设置为包含第一行的高度,深度应为任何其他垂直材料(因此第一行的深度 + 后续行的高度和深度)。然后它必须忽略框的高度,但不能忽略其深度。乍一看,这似乎(在我看来)毫无必要地复杂。
下面,您将看到一张经过编辑的真实案例输出图片,其尺寸(据我所知)是 LaTeX 为对齐生成的垂直框所提供的。我稍微修改了输出的屏幕截图,勾勒出基线和\vskip
算法计算的结果。
在下图中,间距已被手动改变,以(大致)获得所需的输出:
实际用例和细节
(如果您认为您不需要了解任何背景并且已经知道答案,请跳过此部分。)
pdf
我正在尝试使用部分提供的原始宏的扩展集来构建一种替代常规的 marginpars 排版方式pdfLaTeX
。具体来说,我使用 来\pdfsavepos
保存 发出的位置\marginpar
。包含要排版为 marginpar 的材料的框被存储起来以供以后排版(这将在 期间发生\output
,即构建页脚时)。为此,它将一个宏附加到\@evenfoot
和\@oddfoot
。简而言之,
- 计算对应于文本列顶部的页面绝对高度。
- 提取发出的高度
\marginpar
(附加到\marginpar
命令)。 - 构建(但不排版)所生成的两个框
\marginpar
(一个用于左侧,一个用于右侧)。 - 计算所需的
\vskip
计算对齐第一行来自论点的材料与发生\marginpar
的行对齐\marginpar
。
我不会详细介绍代码(如果您有兴趣,可以在我的另一个问题中阅读):使用 pdfsavepos 重新排版 marginpars)。现在,我将直接跳到相关部分,这些部分主要与正确设置间距有关。
问题如下:\pdfsavepos
保存了基线发出命令的地方。请看下面的图片:(如果您看不懂小字,这里还有一个 StackExchange 图片的链接:https://i.stack.imgur.com/2J1An.png。
当然,我可以简单地设置一个负数\vskip
,-8.14\p@
然后就完成了。对于可变的字体大小和不同的字体,问题变得更加复杂。下面的文档在控制台中显示了我必须将框升高多少才能获得所需的对齐方式(只是\rule
为了更清楚地显示基线):
\documentclass{article}\usepackage{fix-cm}\begin{document}
\count0=0
\loop
\ifnum\count0<20
\advance\count0by1
\typeout{The following amount of overfull vbox corresponds to font size: \the\count0}%
\hfill\rule{\linewidth}{1pt}\rlap{\fontsize{\count0pt}{0pt}\selectfont
\textsuperscript{1}\hskip-\marginparsep\smash{\raise0pt%8.5pt
\vbox to 0pt{\hbox{\fontsize{\count0pt}{0pt}\selectfont
\textsuperscript{1}stuff}}}}%
{\fontsize{\count0pt}{0pt}\selectfont %\typeout{fontsize\the\count0:\the\fontcharht\font`1}%
}%
\repeat
\end{document}
\textsuperscript
上面显示,线和 ped 框之间的顶部差异\rlap
确实是8.14
点,这也会在主文档中产生所需的对齐。
此时,我正在考虑一种\ifcase
构造,将字体大小转换为所需\vskip
大小以获得所需的对齐方式。这不是很通用,需要对所有可能的字体大小进行广泛检查,等等。我可以想到一个更通用的解决方案。与 David Carlisle 的简短聊天让我想到了其他解决方案:我甚至不应该知道这些高度,而且我的解决方案从一开始就是错误的。(我应该使用\vtop
。)我尝试\vbox
用 s 替换任何 es \vtop
,但无济于事。我可以看到\vtop
其他情况下的工作,但我看不出它在这种情况下会如何工作。看这个例子:
\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}\def\exx{\hbox to .45\linewidth{\ex}}
\begin{document}
\setbox0=\vbox{\exx\exx\exx}
\setbox2=\vtop{\exx\exx\exx}
Sample text \box0
\vskip20pt
\textsuperscript{1}\box2
\end{document}
第二个框仍然产生错误的对齐。我不确定这是否与我的使用有关,或者操作是否只是没有按照我想要的方式进行。
该尺寸8.14pt
显然来自于的高度\textsuperscript
(1
我认为其字体大小为 5 \normalsize
[对吗?!])按照“TeX 书”附录 G 中的计算增加了一些量。我显然想将其推广到任意字体大小、第一行的任意高度等。
平均能量损失
再次强调,这个问题是间距问题。考虑以下 MWE:
\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}
\def\exx{\hbox to .45\linewidth{\ex}}
\def\textone{\textsuperscript{1}}
\def\textonerepeat{\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone}
\begin{document}
\setbox0=\vbox{\exx\exx\hbox to .45\linewidth{\textonerepeat\textonerepeat\textonerepeat}}
\setbox2=\vtop to 0pt{\exx\vskip0pt \exx\exx}
Sample text \box0 %\raise8.14pt
\box2
\end{document}
通过取消注释,我得到了正确的对齐方式\raise8.14pt
:
(在右边的图片中,我已经改变了截图以显示基线,并显示了轮廓\box2
。)
是否有任何操作、维度或其他方式可以获得所需的对齐方式(如右图所示)?我正在考虑类似\topisbaseline\box0
或类似的东西。解决方案必须适用于任意字体大小和(最重要的是)任意字体。
答案1
这个问题太长了,实际上无法考虑,而且我完全不明白改变后的图像。
在这个版本的 MWE 中,我用红色标记了外部的sample text
、\box0
和的基线\box2
,它们都自然地对齐在该基线上,而无需测量 box2 的高度(这取决于所使用的字体)。
\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}
\def\exx{\hbox to .45\linewidth{\ex}}
\def\textone{\textsuperscript{1}}
\def\textonerepeat{\textone\textone\textone
\textone\textone\textone\textone\textone
\textone\textone\textone}
\begin{document}
\setbox0=\vbox{\exx\exx\hbox to .45\linewidth{%
\textonerepeat\textonerepeat\textonerepeat}}
\setbox2=\vtop{\hbox{\textone\ex}\exx\exx\exx}
Sample text \box0 %\raise8.14pt
\showthe\ht2
\box2
\end{document}
如果由于某种原因您确实需要 8.14pt 长度,则您不需要任何特定于字体的计算,这很简单\ht2
(这就是为什么您在保存 box2 时不应该使用它,... to 0pt
因为它的主要作用是隐藏这个长度)。
我已添加\showthe\ht2
,因此 TeX 停止并显示:
> 8.14003pt.
l.13 \showthe\ht2