页面不完整,图片重叠

页面不完整,图片重叠

下面的示例给出了重叠的图形(图形与自身重叠以及图形与文本重叠),如下图所示。

h如果我更改周围的文本、图像大小或删除第二个图形的 -placement 修饰符,我可以解决这个问题。使用\raggedbottom重叠也会消失。该示例给出了 vbox 未满警告,但在出现这些警告的其他页面上,LaTeX 只会拉伸垂直跳跃,因此它看起来不再那么好,但至少它仍然可读。

那么为什么会发生这种情况?有没有办法解决这个问题,而不用重写一些文本或不把图放在“这里”?

在此处输入图片描述

\documentclass[parskip=half]{scrbook}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\begin{document}

\begin{figure}[th]
    \fbox{\parbox[c][6cm]{7cm}{img 1}}
    \caption{caption 1}
\end{figure}

x\\x\\x\\x\\x\\x\\x\\x\\x\\x\\x

\begin{figure}[th]
    \raggedleft
    \fbox{\parbox[c][4cm]{5cm}{img 2}}
    \caption{caption 2}
\end{figure}

\section{A section}
y\\y\\y\\y\\y

\end{document}

答案1

多么有趣的问题啊!

事实证明,这(可能是)自古以来 LaTeX 就存在的一个错误,但由于它涉及到非常微妙的领域(TeX 有其局限性),即使我们想尝试它,我也不确定是否有安全的解决方案 --- 我稍后会提供一个解决方案,但可能存在我还没有想到的其他问题。

那么问题是什么?首先我们需要一些非常特殊的情况

  • scrbook有选项parskip=half是必需的
  • 该页面需要一些非常特殊的结构
  • 浮子h需要位于最底部

可以进一步缩短 MWE,这有助于我查明问题所在:

\documentclass[parskip=half]{scrbook}

\tracingonline1\tracingpages1

\begin{document}

\begin{figure}[th]
    \fbox{\parbox[c][6cm]{7cm}{img 1}}
    \caption{caption 1}
\end{figure}

x\\x\\x\\x\\x\\x\\x\\x\\x\\x\\x

\begin{figure}[h]
    \raggedleft
    \fbox{\parbox[c][4cm]{5cm}{img 2}}
    \caption{caption 2}
\end{figure}

\addvspace{3cm}
\addpenalty{-300}

Z

\end{document}

我添加的最重要的一行是

\tracingonline1\tracingpages1

这让我们跟踪了页面中断的情况。如果我们运行它,我们会得到

%% goal height=595.80026, max depth=5.5
% t=0.0 g=595.80026 b=10000 p=0 c=100000#
% t=11.0 g=595.80026 b=10000 p=-10003 c=-10003#
%% goal height=595.80026, max depth=5.5
% t=0.0 g=595.80026 b=10000 p=0 c=100000#
% t=202.1165 g=595.80026 b=10000 p=0 c=100000#
% t=227.7165 plus 2.0 minus 2.0 g=595.80026 b=10000 p=150 c=100000#
% t=241.31651 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=254.91652 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=268.51653 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=282.11653 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=295.71654 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=309.31654 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=322.91655 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=336.51656 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=350.11656 plus 2.0 minus 2.0 g=595.80026 b=10000 p=150 c=100000#
% t=363.71657 plus 2.0 minus 2.0 g=595.80026 b=10000 p=-10004 c=-10004#
%% goal height=16383.99998, max depth=5.5
% t=11.0 g=16383.99998 b=10000 p=-10003 c=-10003#
%% goal height=595.80026, max depth=5.5
% t=0.0 g=595.80026 b=10000 p=0 c=100000#
% t=202.1165 g=595.80026 b=10000 p=0 c=100000#
% t=227.7165 plus 2.0 minus 2.0 g=595.80026 b=10000 p=150 c=100000#
% t=241.31651 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=254.91652 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=268.51653 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=282.11653 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=295.71654 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=309.31654 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=322.91655 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=336.51656 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=350.11656 plus 2.0 minus 2.0 g=595.80026 b=10000 p=150 c=100000#
% t=363.71657 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=520.92757 plus 4.0 minus 4.0 g=595.80026 b=10000 p=0 c=100000#
% t=526.12756 plus -0.8 minus 6.0 g=595.80026 b=10000 p=-300 c=100000#
% t=631.88583 plus 6.0 minus 6.0 g=595.80026 b=* p=0 c=*

Underfull \vbox (badness 10000) has occurred while \output is active []

这显示了如何添加第一个浮点数,c=-10003然后添加所有带有浮点数的行,x直到我们有

% t=363.71657 plus 2.0 minus 2.0 g=595.80026 b=10000 p=-10004 c=-10004#

对应于此处的第二个浮动。此时页面已重建,因此我们会看到所有行再次出现,然后以此结尾:

% t=363.71657 plus 2.0 minus 2.0 g=595.80026 b=10000 p=0 c=100000#
% t=520.92757 plus 4.0 minus 4.0 g=595.80026 b=10000 p=0 c=100000#
% t=526.12756 plus -0.8 minus 6.0 g=595.80026 b=10000 p=-300 c=100000#
% t=631.88583 plus 6.0 minus 6.0 g=595.80026 b=* p=0 c=*

第一行是最后x一行,然后出现了一个很大的跳跃,t=因为我们在这里添加了第二个浮点数,然后t=526.12756我们看到一个p=-300IE,我们的明确惩罚。我们没有看到空间,3cm因为\addpenalty将自己移动到了前面的跳过之前。

最后一行意味着c=*我们有太多的内容(现在增加了 3 厘米)。因此,分页符是在前面一行的明确惩罚处进行的,IE, 在

% t=526.12756 plus -0.8 minus 6.0 g=595.80026 b=10000 p=-300 c=100000#

现在如果你看一下这个跟踪输出(并且你已经准备好了 TeXbook,或者 LaTeX Companion,或者你已经记住了这些东西 :-)),那么你会注意到为什么页面会这样显示... 你注意到了吗? 不?

好的,我们开始吧:

  • 页面高度为,t=526.12756但页面目标是,g=595.80026所以我们太短,页面材料需要拉伸;
  • 然而,拉伸部分plus -0.8在这条线上实际上是负的(而且只有这条线),所以为了从到拉伸,526pt我们595pt必须将其乘以-86(大致);
  • 因此 TeX 继续将页面上所有粘连的“加号”部分乘以-86
  • 现在,在第一个浮点数之后有一个粘合,即12pt plus 2pt minus 2pt,所以如果将它的加号部分相乘,-86我们就会得到总共的12pt plus -172pt跳过,这将-es-150pt的线向上驱动;x
  • 同样的,在第二个浮标的前面也有这样一个空间,这样人们就可以驱动浮标向上移动-150pt,这就是你发送的内容。

因此剩下的问题是,为什么我们最终会在这条线上得到这个负的“加号部分”?

这个问题的答案隐藏在一个名为的宏中,\@addcurcol该宏的任务是将浮点数附加到适当的位置。如果出现“此处浮点数”,它将执行以下代码:

               \vskip \intextsep
               \box\@currbox
               \penalty\interlinepenalty
               \vskip\intextsep
               \ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi

在它的最后,它会在某些情况下发出问题(当在垂直模式下遇到浮动时)\vskip - \parskip,并且\parskip由于6.8pt plus 6.8pt选择,scrbook我们最终得到

\vskip -6.8pt plus -6.8pt

并将页面上其余的加号部分完全加上6pt(你可以在上面的描图中看到)我们得到了整体plus -0.8……然后我们就得到了……叹息。

那么这里出了什么问题?这个负数\parskip被添加到此处的浮动之后,以说明另一个即将被添加的事实\parskip,如果我们不将其取消,间距将看起来非常不均匀 --- 尤其是如果您\parskip一开始就有一个较大的浮动,如示例中所示。

但是,在我们的示例中,我们最终在它之后得到了一个分页符,因此后面没有任何需要取消的 parskip,所以我们有这个额外的负数,它确实搞乱了页面计算。

换句话说,分页符不应该出现在那里,而应该出现在负数之前\parskip,或者实际上应该出现在\intextsep浮动元素之后。但这很难安排。像\addpenalty或 这样的元素\addvspace永远看不到这个空间(因为它是在输出例程中添加的,当输出例程结束时,您将自动\penalty 10000在最后添加一个,这会隐藏之前的任何内容。

所以我尝试了一种不同的方法:

  • 计算输出例程中要添加的空间(\intextsep或);\intextsep - \parskip
  • \vskip然后仅在输出例程结束后通过使用将其推出来添加\aftergroup

因此将其应用到原始 MWE 我们得到:

\documentclass[parskip=half]{scrbook}

\tracingonline1\tracingpages1

\usepackage{etoolbox}

\makeatletter

\patchcmd\@addtocurcol
    {\vskip\intextsep  \ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi}
    {\calc@after@float@skip
      \aftergroup\add@after@float@skip}
    {\typeout{Patch Successfully applied}}{\typeout{Patch failed!}\ERROR}

\def\calc@after@float@skip{
   \@tempskipa\intextsep
   \ifnum\outputpenalty <-\@Mii \advance\@tempskipa-\parskip \fi
   \xdef\add@after@float@skip{\vskip\the\@tempskipa\relax}%
}

\makeatother

\begin{document}

\begin{figure}[th]
    \fbox{\parbox[c][6cm]{7cm}{img 1}}
    \caption{caption 1}
\end{figure}

x\\x\\x\\x\\x\\x\\x\\x\\x\\x\\x

\begin{figure}[h]
    \raggedleft
    \fbox{\parbox[c][4cm]{5cm}{img 2}}
    \caption{caption 2}
\end{figure}

\section{A section}
y\\y\\y\\y\\y

\end{document}

结果是

在此处输入图片描述

但不能保证这不会改变其他文档,因为这现在会改变此处靠近页面末尾的浮动后的间距。

答案2

因此,这是一个不幸的时机,在这里将两个浮动元素添加到空白页,并决定是否在节标题处中断。

到目前为止还没有完全追踪它(我可能会放弃并问弗兰克:-)但你可以通过\clearpage在该部分之前添加无论如何都会中断页面​​的点来简化乳胶的决策。

在此处输入图片描述

\documentclass[parskip=half]{scrbook}
\usepackage{fltrace}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\begin{document}
\tracefloats
\begin{figure}[th]
    \fbox{\parbox[c][6cm]{7cm}{img 1}}

   \caption{caption 1}
\end{figure}

x\\x\\x\\x\\x\\x\\x\\x\\x\\x\\x

\begin{figure}[th]
    \raggedleft

    \fbox{\parbox[c][4cm]{5cm}{img 2}}

    \caption{caption 2}
\end{figure}
\clearpage
\section{A section}
y\\y\\y\\y\\y

\end{document}

相关内容