在可破坏的 tcolorbox 之前取消分页符

在可破坏的 tcolorbox 之前取消分页符

我试图避免在分段命令和后面的 tcolorbox 之间出现分页符。对于“普通”框,我可以使用\nopagebreak,例如在before选项中:

\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum,needspace}
\tracingpages=1
\begin{document}
\lipsum[1-4]

\section{title}
\begin{tcolorbox}[before=\nopagebreak,
                  %breakable, %
                  ]
\rule{1cm}{10\baselineskip}
\lipsum[1]
\end{tcolorbox}

\end{document}

但如果我激活该breakable选项,这将失败。有一个我无法识别的断点。有人知道它在哪里以及我如何抑制它吗?\Needspace有帮助,但必须知道 tcolorbox 开头的对象的大小。

答案1

以下补丁可用于tcolorbox版本3.32及之前的版本。它已整合到tcolorbox版本3.33 (2014/12/11)及更高版本。要恢复之前的旧行为,可以应用3.33该选项。ignore nobreak

正如我在评论中所写,我担心这个问题没有全局解决方案。但我尝试了一个补丁,它可能对许多用例都有帮助。补丁代码试图估计标题后所需的空间。如果框或框的第一部分很可能不适合当前页面,则应用\vspace{...}\null\vspace{-...}您的技巧将所有内容(包括标题)移动到下一页。

如果框中包含大量不可破坏的内容(如您的示例所示),则空间估计可能会失败。在这种情况下,会发出警告以检测长文档中的此类问题。一种手动解决方案是将值放大lines before break以匹配不可破坏的内容。目前,我还没有看到自动方法。

以下代码是一个实验性补丁。如果它被证明是稳定的,我想把它放到正式版本中,但在此之前必须进行许多测试。如果您发现(新的)问题,或者您可以改进它,请随时发表评论。主要部分是\tcb@handle@nobreak,其余部分是一些略微更改的当前代码。

\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum}
\tracingpages=1

\makeatletter

\def\tcb@do@nobreak@warning{%
  \tcb@warning{Using nobreak failed. Try to enlarge `lines before break' or set page breaks manually}%
}

\def\tcb@handle@nobreak{%
  \tcb@enlbreak@init%
  \tcb@breakat@init%
  \tcb@comp@h@page%
  \tcbdimto\tcb@h@page{\tcb@h@page-\baselineskip}% security surcharge
  \tcb@comp@h@total@standalone%
  \tcb@check@for@final@box%
  \iftcb@final@box%
  \else%
    \ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
      \tcbdimto\tcb@h@page{\tcb@h@page+3\baselineskip}%
      \vspace{\tcb@h@page}%
      {\parskip\z@\nointerlineskip\noindent}%
      \vspace{-\tcb@h@page}%
    \fi%
  \fi%
}

\def\tcb@prepare@break@operation{%
  \let\tcb@nobreak@warning\@empty%
  \@ifundefined{columnbreak}{\tcb@multicolfalse}{%
    \ifnum\doublecol@number>\z@ %
      \tcb@multicoltrue%
    \else%
      \tcb@multicolfalse%
    \fi}%
  \ifx\kvtcb@float\@empty%
    \if@nobreak%
      \tcb@handle@nobreak%
      \let\tcb@nobreak@warning\tcb@do@nobreak@warning%
    \else%
      \kvtcb@beforebox%
    \fi%
    \def\kvtcb@beforebox{\parskip\z@\nointerlineskip\noindent}%
    \noindent% applies parskip
    \vskip\lineskip{\parskip\z@\par\vskip\z@}\bgroup\@nobreakfalse\addpenalty\z@\egroup% force update vertical list
    \tcb@break@allowedtrue%
    \tcb@enlbreak@init%
  \else%
    \tcb@break@allowedfalse%
  \fi%
}


\def\tcb@split@start{%
  \tcb@breakat@init%
  \tcb@comp@h@page%
  % height calculation
  \tcb@comp@h@total@standalone%
  %
  \let\tcb@split@next=\relax%
  \tcb@check@for@final@box%
  \iftcb@final@box%
    \tcb@drawcolorbox@standalone%
  \else
    \iftcb@break@allowed%
      \ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
        \iftcb@multicol\columnbreak\else\pagebreak\fi%
        \tcb@nobreak@warning%
        \tcb@enlbreak@init\tcb@break@allowedfalse%
        \tcb@comp@h@page%
        \tcb@check@for@final@box%
        \iftcb@final@box%
          \tcb@drawcolorbox@standalone%
        \else
          \let\tcb@split@next=\tcb@split@first%
        \fi
      \else%
        \let\tcb@split@next=\tcb@split@first%
      \fi
    \else%
      \let\tcb@split@next=\tcb@split@first%
    \fi%
  \fi%
  \tcb@split@next%
}


\def\tcb@split@first{%
  \setcounter{tcbbreakpart}{1}%
  \ifx\kvtcb@float\@empty%
    \iftcb@vfillbeforefirst%
      \let\tcb@before@first=\vfill%
    \else%
    \let\tcb@before@first=\@empty%
    \fi%
    \let\tcb@before@middle=\@empty%
    \let\tcb@before@last=\@empty%
    \iftcb@multicol%
      \long\def\tcb@after@first{\par}% using \columnbreak here kills multicols' algortihm sometimes
      \long\def\tcb@after@middle{\par\vfill}%
    \else%
      \long\def\tcb@after@first{\par\pagebreak\tcb@enlbreak@next}%
      \long\def\tcb@after@middle{\par\vfill\eject\tcb@enlbreak@next}%
    \fi%
    \let\tcb@after@last=\par%
  \else%
    \edef\tcb@before@first{\noexpand\tcb@float@env@begin{tcbfloat}[\kvtcb@float]\noexpand\kvtcb@everyfloat}%
    \let\tcb@before@middle=\tcb@before@first%
    \let\tcb@before@last=\tcb@before@first%
    \let\tcb@after@first=\tcb@float@env@end%
    \let\tcb@after@middle=\tcb@float@env@end%
    \let\tcb@after@last=\tcb@float@env@end%
  \fi%
  %
  \edef\kvtcb@skin@@first{\kvtcb@skin@first}%
  \edef\kvtcb@skin@@middle{\kvtcb@skin@middle}%
  \edef\kvtcb@skin@@last{\kvtcb@skin@last}%
  %
  \let\tcb@h@breaksep@first=\kvtcb@bottomsep%
  \tcbdimto\tcb@h@breaksep@middle{\kvtcb@bottomsep+\kvtcb@topsep}%
  \let\tcb@h@breaksep@last=\kvtcb@topsep%
  \tcbdimto\tcb@h@padding@first{\kvtcb@bbtop@stand+\kvtcb@bbbottom@break+\kvtcb@top@rule@stand+\kvtcb@bottom@rule@break+\tcb@h@breaksep@first+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
  \tcbdimto\tcb@h@padding@middle{\kvtcb@bbtop@break+\kvtcb@bbbottom@break+\kvtcb@top@rule@break+\kvtcb@bottom@rule@break+\tcb@h@breaksep@middle+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
  \tcbdimto\tcb@h@padding@last{\kvtcb@bbtop@break+\kvtcb@bbbottom@stand+\kvtcb@top@rule@break+\kvtcb@bottom@rule@stand+\tcb@h@breaksep@last+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
  %
  \tcb@split@setstate@first%
  %
  \splittopskip=0pt%
  \splitmaxdepth=0pt%
  \edef\tcb@thevfuzz{\the\vfuzz}%
  \edef\tcb@thevbadness{\the\vbadness}%
  %
  \tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
  \tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
  %
  \let\tcb@split@next=\relax%
  \tcbdimto\tcb@split@dim{\tcb@h@page-\tcb@h@padding@first-\tcb@h@padtitle}%
  \ifdim\tcb@split@dim<\tcb@h@upper\relax%
    \tcb@split@upper@box%
    \ifdim\wd\tcb@totalupperbox=0pt\relax%
      \iftcb@lowerspace%
        \tcb@sdraw@U%
        \let\tcb@split@next=\tcb@split@SL%
      \else%
        \tcb@split@force@standalone%
        \tcb@drawcolorbox@standalone%
      \fi%
    \else%
      \ifdim\dimexpr\tcb@h@upper=0pt\relax%
        \iftcb@break@allowed
          \tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
          \tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
          \tcbdimto\tcb@h@upper{\ht\tcb@upperbox+\dp\tcb@upperbox}%
          \tcbdimto\tcb@h@lower{\ht\tcb@lowerbox+\dp\tcb@lowerbox}%
          \iftcb@multicol\columnbreak\else\pagebreak\fi%
          \tcb@nobreak@warning%
          \tcb@enlbreak@init\tcb@break@allowedfalse%
          \let\tcb@split@next=\tcb@split@start%
        \else%
          \tcb@sdraw@U%
          \let\tcb@split@next=\tcb@split@USL%
        \fi%
      \else%
        \tcb@sdraw@U%
        \let\tcb@split@next=\tcb@split@USL%
      \fi%
    \fi%
  \else%
    \tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
    \tcbdimto\tcb@split@dim{\tcb@split@dim-\tcb@h@upper-\tcb@h@segment}
    \ifdim\tcb@split@dim<\kvtcb@breakminlines\baselineskip\relax%
      \tcb@sdraw@U%
      \iftcb@lowerspace%
      \let\tcb@split@next=\tcb@split@SL%
      \else%
      \let\tcb@split@next=\tcb@split@USL%
      \fi%
    \else
      \tcb@split@lower@box%
      \ifdim\wd\tcb@totallowerbox=0pt\relax%
        \tcb@split@force@standalone%
        \tcb@drawcolorbox@standalone%
      \else%
        \tcb@sdraw@USL%
        \let\tcb@split@next=\tcb@split@L%
      \fi%
    \fi%
  \fi%
  \tcb@split@next%
}

\makeatother


\begin{document}
\lipsum[1-4]

\section{title}
\begin{tcolorbox}[enhanced,breakable,%
                  lines before break=10,% commenting this issues a warning
                  ]
\rule{1cm}{10\baselineskip}
\lipsum[1]
\end{tcolorbox}


\clearpage
\lipsum[1-4]

\rule{1cm}{6mm}

\section{Normal case}%
\begin{tcolorbox}[enhanced,breakable]
\lipsum[1]
\end{tcolorbox}

\end{document}

在此处输入图片描述

相关内容