将页面插入 LaTeX 的浮动材料队列

将页面插入 LaTeX 的浮动材料队列

我有一个奇怪的格式要求。对于图形及其标题太大而无法放在一页上的情况,标题需要单独出现在标题之前的页面上。此外,此页面的格式非常具体(并且涉及几何变化,这很像双面打印中的偶数页,即使文档是单面的,参见此问题—这要怪设计论文格式要求的人,而不是我)。

构建带有标题的页面和带有图片的页面非常简单。我需要的是一种将材料插入到 LaTeX 用于输出图片的任何队列中的方法,并进一步确保两个页面保持在一起。

请注意,我不想使用\FloatBarrier宏,因为目标不是现在开始输出浮点数,我只需要添加两个新的浮点数并让它们保持在连续的页面上。

它看起来有点像我可以用\@freelist它来抓取插入号、为页面构建一个框,然后导致调用输出例程,但内核源代码对我来说还不清楚。

答案1

以下是我在 ConTeXt 中执行此类操作的方法。也许这会给你一些关于 LaTeX 解决方案的想法。

解决方案的关键是两个属性

  1. 可以在一个页面上只放置一个浮动对象。在 ConTeXt 中,你可以使用

    \placefigure[...][page]{....}{....}
    

    我不知道pLaTeX 中的浮点数说明符是否以相同的方式工作。

  2. 能够插入任意文本下一个页面。在 ConTeXt 中,您可以使用

    \startpostponing[+1] .... \stoppostponing
    

    事实上,除了+1,您还可以使用+2在两页后插入一些内容,等等。我不知道是否有提供此功能的 LaTeX 包。

那么,解决方案就是将这两个特征结合起来:

\开始推迟[+1]
\placefigure[page]{图片标题}{\strut}
\页
\placefigure[page,nonumber]{}
    {\externalfigure[...][width=\textwidth,height=\textheight]}
\停止推迟

在我尝试的几个例子中,这似乎有效。这是一个完整的工作示例:

\useMPlibrary[dum] %用于虚拟图形

% 任意文本
\启动缓冲区
\dorecurse{5​​}{
\输入 knuth \endgraf
\dorecurse{4}
{
\placefigure[此处,顶部,底部]
  {任意浮动图形}
  {\externalfigure[dummy][宽度=0.4\textwidth,高度=0.3\textheight]}
}
\输入 knuth \endgraf
}
\停止缓冲区

\开始文本

\获取缓冲区
\开始推迟[+1]
\placefigure[page]{图片标题}{\strut} \page
\placefigure[page,nonumber]{}{\externalfigure[dummy][width=\textwidth,height=\textheight]}
\停止推迟
\获取缓冲区

\停止文本

答案2

下面的代码似乎在极少的测试下工作(即单面、单列、没有颜色)。不过这是一个相当大的 hack。我绝对愿意接受更好的方法来实现这一点或改进此代码。

代码分为两部分。第一部分是一个新的浮动环境。

\newbox\my@captionbox
\newenvironment{facingcaption}[1]{%
    \let\my@saved@caption\@caption
    \global\setbox\my@captionbox\box\voidb@x
    \long\def\@caption##1[##2]##3{%
        \global\setbox\my@captionbox\color@vbox\vbox{%
            \my@saved@caption##1[##2]{##3}%
        }\color@endbox
        \def\caption{\ClassError{mydissertation}{%
            Only one \noexpand\caption\space per
            facingcaption}{}}%
    }%
    \@xfloat{#1}[p]%
}{%
    \@endfloatbox
    \let\@endfloatbox\relax
    \ifvoid\my@captionbox\else
        \ht\my@captionbox\z@
        \dp\my@captionbox1sp
        \global\setbox\@currbox\vbox{%
            \box\@currbox
            \nointerlineskip
            \box\my@captionbox
            \vskip-1sp
        }%
        \ht\@currbox\textheight
    \fi
    \end@float
}

该代码重新定义\@caption,以便它在 内排版标题\vbox。(我不确定是否需要颜色。它似乎没有坏处,至少在未使用颜色时。)

然后,它不再以 结束浮动\end@float,而是以 — 开始的框结束浮动\@xfloat,这通常是以 结束的\end@float,因此将其设置为\relax。如果标题框不是空的,则当前浮动框\@currbox将被重新定义为由\vbox3 个项目组成的:原始 中的浮动材料\@currbox、高度为 0 且深度为 1sp 的标题框以及跳跃为 -1sp 的框。最后,我们将框的高度设置为 ,\textheight以便输出例程在实际构建页面时自行将浮动粘贴在页面上。

最后,\end@float实际上会调用输出例程两次,这将导致浮点数进入延迟列表,但实际上不会构建和输出任何页面。

代码的第二部分是对输出例程的修改。在实际生成输出页面时,将逐个处理浮点列表。由于框具有适合页面的最大高度,因此它将单独放置。特别是,将对\@wtryfc适合页面的框列表中的每个框执行 。通常,它只是将其参数(框)和一些空间添加到\@outputbox

如果输出框的高度为 0,此代码就会劫持并调用我自己的例程(这只是一种优化)。

\let\my@saved@wtryfc\@wtryfc
\def\@wtryfc#1{%
    \ifdim\dimexpr\ht\@outputbox + \dp\@outputbox=\z@
        \my@wtryfc{#1}%
    \else
        \my@saved@wtryfc{#1}%
    \fi
}

\my@wtryfc需要检查其参数是否是这些特殊框之一。它通过取消装箱来做到这一点,检查最后一个跳过是否为 -1sp,并且之前的框的深度为 1sp。如果是,则将其取消装箱并保存。最后,唯一剩下的框(参数中的第一个框\@wtryfc)是原始图形框,因此保存它。

\newbox\my@outputcaptionbox
\newbox\my@outputfigurebox
\def\my@wtryfc#1{%
    \begingroup
    \global\setbox\my@outputcaptionbox\box\voidb@x
    \setbox\z@\vbox{%
        \unvcopy#1%
        \ifdim\lastskip=-1sp
            \unskip
            \setbox\z@\lastbox
            \ifdim\dp\z@=1sp
                \global\setbox\my@outputcaptionbox\vbox{%
                    \unvbox\z@
                }%
                \global\setbox\my@outputfigurebox\lastbox
            \fi
        \fi
    }%
    \ifvoid\my@outputcaptionbox
        \my@saved@wtryfc{#1}%
    \else
        \if\dim\dimexpr\ht\z@+\dp\z@>\z@
            \message{Output box not torn apart!}%
        \fi
        \global\setbox\@outputbox\vbox to\textheight{%
            \vfill
            \box\my@outputcaptionbox
            \vfill
            \vfill
        }%
        \my@savespecial
        \ps@facingcaption
            \@specialpagefalse
        \@outputpage
        \my@restorespecial
        \global\setbox\@outputbox\vbox{}%
        \my@saved@wtryfc{\my@outputfigurebox}%
    \fi
    \endgroup
}

\def\my@savespecial{%
    \let\my@specialpage\if@specialpage
}
\def\my@restorespecial{%
    \global\let\if@specialpage\my@specialpage
}

\vbox{figure}\vbox{caption}\vskip-1sp在 中查找 之后\setbox,如果没有发现标题框,则使用 LaTeX 的常规方法\@wtryfc将框添加到\@outputbox。否则,在 中构建一个与对面标题页相对应的框\@outputbox。保存特殊的页面样式条件(这可能是不必要的,我不确定),然后facingcaption执行页面样式的页面样式命令(\thispagestyle{facingcaption}不适\AtBeginShipout用于包使用的 ,showframes因为边距需要更改)。接下来,它实际使用 输出的页面\@outputpage。清除 并对图形框执行\@outputbox常规操作。\@wtryfc

相关内容