在 ConTeXt 中,列不必要地跳过页面

在 ConTeXt 中,列不必要地跳过页面

我有块级命令,用 tikz 绘制的水平线包围一些内容。它在大多数情况下工作正常,但当我在分页符的位置使用它时,内容是一个columns环境,ConTeXt 会生成一个几乎空白的页面。这是一个 MCVE:

\usemodule[tikz]
\usetikzlibrary[positioning,fit,calc]

\definestartstop[Solution][before={
  \blank[0.5em,preference]
  \starttikzpicture
    \node[rectangle,draw=black,anchor=north west] (header) {\bfxx\ss Sample Solution};
    \draw[line cap=rect,draw=black] (header.north east) ++(0,-\pgflinewidth/2) -- (\textwidth-\pgflinewidth,-\pgflinewidth/2);
  \stoptikzpicture
  \blank[0.5em,samepage]
},after={
  \blank[0.125em,samepage]
  \starttikzpicture
    \draw[black] (0,0) -- (\textwidth-\pgflinewidth,0) -- ++(0,0.25cm);
  \stoptikzpicture
}]

\starttext
  \dontleavehmode \vfill
  \blank[26.5cm]

  Lorem Ipsum

  \startSolution
    \startcolumns[n=2]
      \input Knuth
    \stopcolumns
  \stopSolution
\stoptext

生成的 PDF 如下所示:

第 1 和 2 页

第 3 页

如您所见,columns尽管第二页(完全空白)上有足够的空间,但 ConTeXt 将整个块移至第三页。

从我的测试来看,问题似乎来自 tikz 和列的交互;如果我删除列,内容就会放在第二页;如果我用正常的替换 tikz 行,情况也是一样\hrule

我怎样才能解决这个问题?

答案1

这与 TikZ 无关。下面是一个显示相同行为的更简单示例:

\starttext
  \dontleavehmode \vfill
  \blank[26.5cm]

  Lorem Ipsum

  \vbox to \lineheight{Solution}

  \startcolumns[n=2]
    \input knuth
  \stopcolumns
\stoptext

出现分页符的原因在于,在初始化期间\startcolumn使用了:

   \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
     \allowbreak
   \else
     \break 
   \fi

将其添加到测试文档中表明我们得到了相同的行为:

\starttext
  \dontleavehmode \vfill
  \blank[26.5cm]

  Lorem Ipsum

  \vbox to \lineheight{Solution}

   \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
     \message{YES}%
     \allowbreak
   \else
      \message{NO}%
     \break 
   \fi

    \input knuth
\stoptext

输出显示NO,这意味着\break正在插入 (而不是\allowbreak)。

我还没有进一步测试,但我猜测会发生以下情况。ConTeXt(而不是 TeX)\startcolumn在第一页时读取代码。然后检查页面上剩余的空间,并插入一个\break。现在,在实际排版完成时,您会Solution因为 而得到一个分页符\break

在以下两个例子中,我在\page之前插入一个\vbox(强制 TeX 弹出上一页),一切正常:

简单示例:

\starttext
  \dontleavehmode \vfill
  \blank[26.5cm]

  Lorem Ipsum

  \page

  \vbox to \lineheight{Solution}

   \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
     \message{YES}%
     \allowbreak
   \else
      \message{NO}%
     \break 
   \fi

    \input knuth
\stoptext

原例:

\usemodule[tikz]
\usetikzlibrary[positioning,fit,calc]

\definestartstop[Solution][before={
  \blank[0.5em,preference]
  \starttikzpicture
    \node[rectangle,draw=black,anchor=north west] (header) {\bfxx\ss Sample Solution};
    \draw[line cap=rect,draw=black] (header.north east) ++(0,-\pgflinewidth/2) -- (\textwidth-\pgflinewidth,-\pgflinewidth/2);
  \stoptikzpicture
  \blank[0.5em,samepage]
},after={
  \blank[0.125em,samepage]
  \starttikzpicture
    \draw[black] (0,0) -- (\textwidth-\pgflinewidth,0) -- ++(0,0.25cm);
  \stoptikzpicture
}]

\starttext
  \dontleavehmode \vfill
  \blank[26.5cm]

  Lorem Ipsum

  \page

  \startSolution
    \startcolumns[n=2]
      \input Knuth
    \stopcolumns
  \stopSolution
\stoptext

解决方法 1

现在我们知道了发生了什么,找到解决方法很简单。第一个解决方法是,如果页面上没有足够的空间,只需添加分页符即可。\testpagesync[n]如果页面上没有足够的空间容纳行,可以使用强制分页符来完成此操作n

\definestartstop[Solution][before={
  \testpagesync[5]
  \blank[0.5em,preference]
  \starttikzpicture
    \node[rectangle,draw=black,anchor=north west] (header) {\bfxx\ss Sample Solution};
    \draw[line cap=rect,draw=black] (header.north east) ++(0,-\pgflinewidth/2) -- (\textwidth-\pgflinewidth,-\pgflinewidth/2);
  \stoptikzpicture
  \blank[0.5em,samepage]
},after={
  \blank[0.125em,samepage]
  \starttikzpicture
    \draw[black] (0,0) -- (\textwidth-\pgflinewidth,0) -- ++(0,0.25cm);
  \stoptikzpicture
}]

解决方法 2

另一种解决方法是使用\startsimplecolumns ... \stopsimplecolumns而不是\startcolumns ... \stopcolumns。顾名思义,simplecolumns适用于简单的列。因此,它们不处理浮点数等。根据用途,这可能就足够了。

相关内容