标题与图片精确对齐

标题与图片精确对齐

我想在图片旁边排版一些标题,但这样做时观察到了一些奇怪的行为(至少对我来说)。我使用两个小页面,对于一个最小示例,所有内容都整齐地对齐在基线(图 1)。但是,如果我添加一个\label在标题后添加一个右键,参考点现在似乎位于最底部(图 2)。如果我添加包,也会发生同样的情况,这相当令人惊讶color。只是这一次,即使没有标签,对齐也是“错误的”。

有人可以告诉我参考点是如何受到影响的\label以及color包与此有什么关系吗?

在此处输入图片描述

%!TEX program = lualatex
\documentclass[draft]{article}

\usepackage{lua-visual-debug}
\usepackage[position=bottom,font=footnotesize]{caption}
% \usepackage{color}

\begin{document}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.8\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
  \end{minipage}
\end{figure}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.8\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
    \label{fig:fox}
  \end{minipage}
\end{figure}

\end{document}

答案1

唉,@egreg 的解释虽然引人入胜,但却是错误的。(但我一开始也被骗了,因为我点了赞!:-) 尽管诊断有误,但他建议的治疗方法同样有效,所以如果不是因为一个细节可能会让普通读者感到困惑,我不会费心写这个答案:@egreg 的答案暗示 \label垂直框中作为最后一个出现的命令总是会破坏该框的深度,但事实并非如此。

然而,正确的解释是一个相当长的故事,所以我必须请你耐心等待。让我们首先回顾一下 TeX 计算其构建的垂直框的深度的规则 \vbox(和的规则\vtop\vcenter这些规则相关,但不同),这些规则在TeXbook在第 80 页(底部)和第 81 页(顶部)。一般规则非常简单和自然:构造的深度\vbox是其内部最底部框的深度。此规则有仅有的三个例外:

  1. 当构造的盒子不包含盒子时,这种情况下其深度为零(显而易见);

  2. 当里面的最后一个盒子在\vbox下面的某处有粘连或字距调整时,这种情况下“外部”深度也为零(似乎合理);

  3. 当用户通过设置参数为深度设置了明确的阈值时,\boxmaxdepth在这种情况下阈值会受到尊重(再次显而易见)。

特别是,“whatsit”节点对于最底部框的深度是“透明的”,正如我们将在下面通过一个简单的实验所展示的那样。

现在,如果一个命令在正在构造的\caption中排在最后,在正常情况下,会出现上述例外情况 2,\vbox应用于排版的行(或最后一行),因为该行 在其下方有粘连,即\belowcaptionskip粘连(例如,参见\@makecaption中的 定义classes.pdf,特别是代码行 1122)。这意味着,如果\belowcaptionskip 保留其默认值0pt,则在正常情况下,标题将不是它的基线与封闭框的基线对齐,而是与外部“超出深度”轮廓对齐,如 OP 的第二个示例所示(是的,如果胶水量为零,例外 2 也适用)。所以要问的问题是,“为什么这在第一个例子中没有发生?”

这里的要点是,在这两种情况下,标题都包裹在一个 minipage环境中,并且当此环境结束时执行的代码(包含在宏中\endminipage,参见其定义latex.ltx)除其他外,还会出现问题——啊哈!——一个\unskip;后者是一个 TeX 原始命令,移除当前列表中的最后一个粘合节点。因此,\unskip删除了来自 的粘合 \belowcaptionskip,因此例外 2 不再适用,并且最后一行的深度使其进入封闭框的级别。

“好吧——你问——但是,为什么第二个例子中没有发生这种情况?”现在的重点是该\unskip命令可以删除最后一个粘合节点 仅当它仍然是当前列表中的最后一个节点时。这里 @egreg 的原始解释介入:如果\label命令跟在后面 \caption,那么它会附加(注意: \caption已经完成,所以 以下胶水\belowcaptionskip!)一个“whatsit”节点(它将在诊断跟踪中显示为一个\write节点);\unskip然后会找到这个“whatsit”,不是粘合,因此将完全没有效果。因此,粘合节点\belowcaptionskip将保留,使异常 2 适用。换句话说,命令的存在\label不会直接使上述任何异常适用,它只与阻止\upskip其工作有关。

如果您尝试以下代码,则可以证明上述大多数断言

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}

% \setlength{\belowcaptionskip}{\bigskipamount}

% \makeatletter
% 
% \def\endminipage{%
%     \par
% %     \unskip
%     \ifvoid\@mpfootins\else
%       \vskip\skip\@mpfootins
%       \normalcolor
%       \footnoterule
%       \unvbox\@mpfootins
%     \fi
%     \@minipagefalse   %% added 24 May 89
%   \color@endgroup
%   \egroup
%   \expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}}
% 
% \makeatother

\showboxbreadth = 1000
\showboxdepth = 10
% \tracingoutput = 1



\begin{document}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.99\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
  \end{minipage}
\end{figure}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.99\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
    \label{fig:fox}
  \end{minipage}
\end{figure}

% \showlists

\setbox0 = \vbox{
    \hsize = 10cm
    \prevdepth = 2pt % not actually important
    The quick brown fox jumped over the lazy dog.\par
    \label{box}
}

The depth of \verb|\box0| is \the\dp0.

% \showbox0

\unvbox0

\end{document}

并取消注释其各个部分以尝试不同的替代方案。例如,取消注释

% \setlength{\belowcaptionskip}{\bigskipamount}

将显示\belowcaptionskip第二个示例中的 仍然存在,但第一个示例中不存在。取消注释

% \makeatletter
% 
% \def\endminipage{%
%     \par
% %     \unskip
%     \ifvoid\@mpfootins\else
%       \vskip\skip\@mpfootins
%       \normalcolor
%       \footnoterule
%       \unvbox\@mpfootins
%     \fi
%     \@minipagefalse   %% added 24 May 89
%   \color@endgroup
%   \egroup
%   \expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}}
% 
% \makeatother

将证明环境\unskip末尾的minipage确实是导致胶水被移除的罪魁祸首(当然,也可以使用 包\patchcmd中的实用程序etoolbox,点击此处)。此外,取消注释

% \showlists

将在你的成绩单文件中包括一个启发性的诊断列表(如果你知道如何阅读它);并取消注释

% \showbox0

将生成一个类似的列表,证明\write该命令生成的节点\label确实是里面的最后一个节点\box0(但尽管如此,内部框的深度仍然存在于外层,如排版输出所示)。

另一方面,取消注释

% \tracingoutput = 1

在我们的例子中没有任何用处,因为所有的figures 都有[h]其位置说明符(并且恰好h被 LaTeX 所尊重!)。

我现在很累了,所以我将把有关该 color包的解释“作为练习”保留下来(暗示:打开lua-visual-debug 包装仔细观察...;-)。

我确实说过这是一个很长的故事,但原帖者要求“启发”,而这就是我试图提供的……


补充:“练习”的答案

众所周知,最初的 TeX 根本不处理颜色;为了实现它,该color包(所有其他提供颜色功能的包都基于此包)也利用了正在构建的列表中适当位置包含的“whatsit”节点。特别是,为了在框的末尾正确恢复在其外部有效的颜色设置,使用了一种特殊的机制,即附加某种节点,其中包含渲染设备的适当指令有问题的框。此节点的确切性质以及它在诊断列表中的报告方式取决于所使用的排版引擎;例如,它被报告为 \pdfcolorstack 0 poppdf(La)TeX,或\special{color pop}(La)TeX。无论如何,此节点都会抑制节点的\unskip效果\write

事实上,如果lua-visual-debug包裹不是加载后,包含恢复颜色指令的节点将不是在 OP 的第一个例子中,将其附加到标题的最后一行之后,因为标题本身没有使用颜色。事实上,请考虑上述代码的以下变体:

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{color}

% \setlength{\belowcaptionskip}{\bigskipamount}

% \makeatletter
% 
% \def\endminipage{%
%     \par
% %     \unskip
%     \ifvoid\@mpfootins\else
%       \vskip\skip\@mpfootins
%       \normalcolor
%       \footnoterule
%       \unvbox\@mpfootins
%     \fi
%     \@minipagefalse   %% added 24 May 89
%   \color@endgroup
%   \egroup
%   \expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}}
% 
% \makeatother

\showboxbreadth = 1000
\showboxdepth = 10
% \tracingoutput = 1



\begin{document}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.99\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
  \end{minipage}
\end{figure}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.99\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{\color{red}The quick brown fox jumps over the lazy dog.}
  \end{minipage}
\end{figure}

\begin{figure}[h]
  \begin{minipage}[b]{.6\linewidth}
    \centering
    \rule{0.99\linewidth}{60pt}
  \end{minipage}%
  \begin{minipage}[b]{.4\linewidth}
    \caption{The quick brown fox jumps over the lazy dog.}
    \label{fig:fox}
  \end{minipage}
\end{figure}

% \showlists

\setbox0 = \vbox{
    \hsize = 10cm
    \prevdepth = 2pt % not actually important
    The quick brown fox jumped over the lazy dog.\par
    \label{box}
}

The depth of \verb|\box0| is \the\dp0.

% \showbox0

\unvbox0

\end{document}

如果你编译它,你会注意到第一个图形的标题的下行线确实\label 延伸到基线以下,它既没有使用颜色,也没有后面跟着命令,而其他两个标题的下行线则没有;对于第二个图形,这是由于标题本身内部存在颜色(取消注释\showlists并查看转录文件以了解完整详细信息)。但是,该lua-visual-debug 包(与一起加载时color)在标题框内包含一些彩色线条,因此,在这种情况下,第一个示例的行为与第二个示例相同(因为颜色同样存在于该盒子内)。

答案2

在第一种情况下,标题小页面中的最后一项是标题的第二行。在第二种情况下,最后一项是 TeX 放置的内容,以便稍后在\write辅助文件的指令中对其进行转换。

此项没有深度,因此第二种情况下最后一项的参考点位于小页面的底部。第一种情况下,参考点位于标题第二行的基线。

解决方案:使用

\caption{The quick brown fox jumps over the lazy dog.\label{fig:fox}}

现在,该内容属于该段落,因此参考点的计算方式与第一个示例类似。

相关内容