在页边距较宽的文档中,我想提供一个延伸到页边距区域的图形环境。此外,我还希望将标题文本放置在此区域中,根据图形的位置,位于图形上方或下方。此外,这应该适用于偶数页和奇数页(scrbook
在我的情况下使用,但该twoside
选项也会有相同的效果)。
我最终想要实现的目标可以通过下面的图形得到最好的说明(在 Inkscape 中快速绘制,不用关心不同的尺寸):
首先,我想从\cite
-macros 收集引用并将它们输出到底部的边距中(这是可行的,因此未在 MWE 中显示)。宽图的标题也应该在边距中。如果宽图出现在底部,我希望引用位于边距中图的标题上方。可能也会在顶部边距中输出某些内容。从图中可以看出,它应该在twoside
模式下工作。
为了检测图形的位置,我使用 David Carlisle 建议的代码。要将标题放置在页边距中(页面底部或顶部),我使用Heiko Oberdiek 建议的代码。要测试当前页面是奇数还是偶数,如果使用\ifthispageodd
fromKOMA-Script
并确保图形延伸到外边距,我使用addmargin*
环境 from KOMA-Script
。
除了我选择稍后处理的几个警告之外,该方法在奇数页上按预期工作,但我的新环境的内容 widefigure
不会出现在偶数页上,尽管在相应区域还有剩余空间。
问题是上面提到的两段代码都以某种方式处理输出例程(单词变化标题中的 可能不完全正确),这对我来说是个黑匣子。我只对代码做了一些小改动(将 David 的 重命名\floatswitch
为\@floatswitch
,\foo
改为,\@helper
并更改了 Heiko 用于将注释定位在页边距中的宏的长度参数\put
)。
有人能解释为什么图形内容没有出现在偶数页上(或者更好的是,让它们出现)吗?
由于上面提到的代码片段,MWE 很长。我尝试添加一些注释(在我的代码中),以帮助理解该方法,Heiko 的代码也进行了注释。
\documentclass[paper=a4,11pt]{scrbook}
\usepackage[left=1in,top=1in,headsep=2\baselineskip,
textwidth=26pc,marginparsep=2pc,marginparwidth=12pc,
textheight=44\baselineskip,headheight=\baselineskip]{geometry}
% It took me a while to figure out the (x)color here is not merely used for
% providing color...
\usepackage{xcolor,atbegshi,picture,zref-abspage}
\usepackage{lipsum}
\makeatletter
%\input{../features/widefigures.tex}
% This magic has been posted by David Carlisle on TeX-SX:
% https://tex.stackexchange.com/questions/56017/formatting-floats-differently-based-on-placement
\def\@floatswitch#1#2#3#4{%
\def\@elt##1{\global\value{##1}\the\value{##1}\relax}%
\edef\FS@ckpt{\cl@@ckpt}%
\let\@elt\relax
\hbox to 3sp{%
\vbox{{\FS@ckpt#1\par}}%
\vbox{{\FS@ckpt#2\par}}%
\vbox{{\FS@ckpt#3\par}}%
\vbox{{\FS@ckpt#4\par}}%
\hss}\aftergroup\break}
\def\FS@checkswitch#1{%
\ifdim\wd#1=3sp %
\setbox\z@\box#1%
\begingroup
\vbadness\maxdimen
\setbox\z@\vsplit\z@ to \textheight
\setbox\z@\vbox{\unvbox\z@\global\setbox\@ne\lastbox}%
\setbox\z@\vbox{\unvbox\@ne\unskip\global\setbox\@ne\lastbox}
\setbox\z@\hbox{\unhbox\@ne\unskip
\FS@junk
\global\setbox\@ne\lastbox}%
\endgroup
\else
\global\setbox\@ne\box#1%
\fi}
\def\@comflelt#1{%
\FS@checkswitch#1%
\setbox\@tempboxa
\vbox{\unvbox\@tempboxa\box\@ne\vskip\floatsep}}
\let\saved@cflt\@cflt
\def\@cflt{%
\def\FS@junk{\setbox\z@\lastbox\setbox\z@\lastbox\setbox\z@\lastbox}%
\saved@cflt}
\let\FS@junk\relax
\let\saved@cflb\@cflb
\def\@cflb{%
\def\FS@junk{\setbox\z@\lastbox\setbox\z@\lastbox}%
\saved@cflb}
\def\@helper#1\box\@currbox#2!!{%
\def\@addtocurcol{%
#1%
\let\FS@junk\relax
\FS@checkswitch\@currbox
\box\@ne
#2}}%
\expandafter\@helper\@addtocurcol!!
\def\@wtryfc #1{%
\global\setbox\@outputbox\vbox{%
\unvbox\@outputbox
\vskip\@fpsep
\def\FS@junk{\setbox\z@\lastbox}%
\FS@checkswitch#1%
\box\@ne}}
%
% Provide a macro that allows typesetting into the margin
%
\newcommand\@wide[2]{%#1%
\begin{addmargin*}[0cm]{#1}#2\end{addmargin*}%
}
%
% An environment to deal with figure-like content
%
\newsavebox{\@ContentCollectorBox}
\newenvironment{@CollectContentAndCaption}[1][\linewidth]{%
% This environment collects its content in the box \@ContentCollectorBox,
% the width of the box is given by the optional argument #1 (defaults to
% \linewidth)
% Furthermore, it redefines the \caption macro and saves its content in the
% macros \@CurrCaptionLong and \@CurrCaptionShort.
%
% The box and the two macros are available globally.
\begingroup
\begin{lrbox}{0\null\global\setbox\@ContentCollectorBox}%
\begin{minipage}{#1}
\renewcommand\caption[2][]{%
\gdef\@CurrCaptionLong{##2}%
\ifx\\##1\\
\gdef\@CurrCaptionShort{##2}%
\else
\gdef\@CurrCaptionShort{##1}%
\fi
}%
}{%
\end{minipage}
\end{lrbox}
\endgroup
}
%
% An environment providing a floating figure which extends in the margin.
%
\newenvironment{widefigure}[1][]{%
% Store the optional argument. If provided, add square brackets around.
\ifx\\#1\\
\def\@rgOne{}%
\else
\def\@rgOne{[#1]}%
\fi
%
% Start the environment defined above
\begin{@CollectContentAndCaption}[\dimexpr\textwidth+\marginparsep+\marginparwidth]%
}{%
% End the environment
\end{@CollectContentAndCaption}%
% Start the figure-environment with the optional argument from
% the \begin{widefigure} part. I use \figure here to avoid an
% \expandafter-orgy to expand the argument
\expandafter\figure\@rgOne
% \@floatswitch is a command from within the magic, I just added the @
\@floatswitch{%
% If you comment the \topmarginpar-commands here, the figure content
% will appear at the desired position.
%
% Output the caption.
\topmarginpar{\@CurrCaptionLong}%
% add a rule to the topmargin-collection with a width of zero and the
% height+depth of the box containing the content without the caption
% from the environment used above.
\topmarginpar{\rule{0pt}{%
\dimexpr\ht\@ContentCollectorBox+\dp\@ContentCollectorBox}}%
%
%
% use the content of the widefigure-environment.
%%%
%%% This does not appear on even pages
%%%
\@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}%
}{%
% Same as above. If you comment the \botmarginpar-commands here, the
% figure content will appear at the desired position.
%
\botmarginpar{\@CurrCaptionLong}%
\botmarginpar{\rule{0pt}{%
\dimexpr\ht\@ContentCollectorBox+\dp\@ContentCollectorBox}}%
% The bottom-content appears only on odd pages
\@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}%
}{%
\@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}%
}{%
\@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}%
}
\endfigure
}
%
% This magic has been posted by Heiko Oberdiek
% https://tex.stackexchange.com/questions/69517/send-and-stack-marginpar-to-the-top-or-the-bottom-of-the-page
\providecommand*{\c@zabspage}{\c@abspage}
% * User macros for configuring
%
% \tbmparItemSep is inserted between marginal notes
% \tbmparMiddleSep is inserted between top and bottom marginal notes.
\newcommand*{\tbmparItemSep}{%
\vspace{1ex minus .5ex}%
\hrule
\vspace{1ex minus .5ex}%
}
\newcommand*{\tbmparMiddleSep}{%
\vspace*{0pt plus 1fil}%
}
% * Debug messages
%
\newcommand*{\tbmparDebug}[1]{%
\typeout{[tbmpar] #1}%
}
% * Label management to remember absolute page number
%
% \tbmpar@PageByLabel stores and loads absolute page number from
% label and defines \tbmpar@page with absolute page number or
% zero if the label is not yet available.
\newcount\c@tbmpar@item
\c@tbmpar@item\z@
\newcommand*{\tbmpar@PageByLabel}{%
\global\advance\c@tbmpar@item\@ne
\zref@labelbyprops{tbmpar\the\c@tbmpar@item}{abspage}%
\edef\tbmpar@page{%
\zref@extractdefault{tbmpar\the\c@tbmpar@item}{abspage}{0}%
}%
\zref@refused{tbmpar\the\c@tbmpar@item}%
\tbmparDebug{Item \the\c@tbmpar@item\space on page \tbmpar@page}%
}
% * Box register management
\newcount\c@tbmpar@box
\c@tbmpar@box\z@
\let\tbmpar@boxfreelist\@empty
% Get a new free box register either from the free list or,
% if the free list is empty, allocate a new box register.
\newcommand*{\tbmpar@NextBox}[1]{%
\@next#1\tbmpar@boxfreelist{%
\tbmparDebug{Reused box: #1}%
}{%
\global\advance\c@tbmpar@box\@ne
\expandafter\newbox\csname tbmpar@box\the\c@tbmpar@box\endcsname
\edef#1{\csname tbmpar@box\the\c@tbmpar@box\endcsname}%
\tbmparDebug{New box: #1}%
}%
}
% Put free box in free list.
\newcommand*{\tbmpar@FreeBox}[1]{%
\begingroup
\let\@elt\relax
\xdef\tbmpar@boxfreelist{%
\tbmpar@boxfreelist
\@elt#1%
}%
\tbmparDebug{Free box: #1}%
\endgroup
}
\newsavebox{\tbmpar@box}
% Each marginpar is put in a box that is initialized as
% parbox/minipage.
\newcommand*{\tbmparBoxSetup}{}
\newcommand{\tbmpar@VBox}[1]{%
\vbox{%
\color@begingroup
\hsize\marginparwidth
\edef\tbmpar@restore@ifminipage{%
\if@minipage
\noexpand\@minipagetrue
\else
\noexpand\@minipagefalse
\fi
}%
\@parboxrestore
\@marginparreset
\tbmparBoxSetup
#1%
\tbmpar@restore@ifminipage
\color@endgroup
}%
}
% Macro \tbmpar@marginpar looks for the page, where the margin note
% belongs to, stores the note in a box and appends the box to the
% note collector register of the page.
% Each page is assigned a box collector registers that collect
% the top notes and a register that collect the bottom notes.
% The name of the box register is \tbmpar@<top|bot>box<page>.
\newcommand{\tbmpar@marginpar}[4]{%
\ifhmode
\@bsphack
\fi
\tbmpar@PageByLabel
\ifnum\tbmpar@page>\z@
\setbox\tbmpar@box\tbmpar@VBox{#4}%
\@ifundefined{tbmpar@#1box\tbmpar@page}{%
\tbmpar@NextBox\tbmpar@currbox
\global\expandafter\let
\csname tbmpar@#1box\tbmpar@page\endcsname
\tbmpar@currbox
\global\setbox\tbmpar@currbox=\vbox{%
\unvbox\tbmpar@box
}%
}{%
\tbmparDebug{Use box: \tbmpar@currbox}%
\expandafter\let\expandafter\tbmpar@currbox
\csname tbmpar@#1box\tbmpar@page\endcsname
\global\setbox\tbmpar@currbox\tbmpar@VBox{%
\unvbox#3%
\par
\begingroup
\tbmparItemSep
\endgroup
\unvbox#2%
}%
}%
\fi
\ifhmode
\@esphack
\fi
}
\newcommand*{\topmarginpar}{%
\tbmpar@marginpar{top}\tbmpar@currbox\tbmpar@box
}
\newcommand*{\botmarginpar}{%
\tbmpar@marginpar{bot}\tbmpar@box\tbmpar@currbox
}
% At shipout time we look for the box collector registers of this
% page and set these boxes in the marginpar box with respecting
% \topskip and \maxdepth.
\def\@marginparxpos{0pt}\def\@marginparypos{0pt}%
\AtBeginShipout{%
\AtBeginShipoutUpperLeft{%
%
% I added the following definition of the corresponding lengths to be able
% to distinguish odd and even pages.
%
\ifthispageodd{%
\def\@marginparxpos{\dimexpr
1in+\oddsidemargin+\textwidth+\marginparsep\relax}%
\def\@marginparypos{-\dimexpr
1in+\topmargin+\headheight+\headsep+\textheight\relax}%
}{%
\def\@marginparxpos{\dimexpr
1in+\evensidemargin-\marginparsep-\marginparwidth\relax}%
\def\@marginparypos{-\dimexpr
1in+\topmargin+\headheight+\headsep+\textheight\relax}%
}
\put(%
\@marginparxpos,\@marginparypos%
){%
\begingroup
\global\let\tbmpar@inuse=N%
\setbox\tbmpar@box=\tbmpar@VBox{%
\penalty-\@M
\edef\tbmpar@tmp{tbmpar@topbox\the\value{zabspage}}%
\@ifundefined{\tbmpar@tmp}{%
}{%
\expandafter\let\expandafter\tbmpar@currbox
\csname\tbmpar@tmp\endcsname
\unvbox\tbmpar@currbox
\tbmpar@FreeBox\tbmpar@currbox
\global\let\tbmpar@inuse=Y%
}%
\endgraf
\tbmparMiddleSep
\edef\tbmpar@tmp{tbmpar@botbox\the\value{zabspage}}%
\@ifundefined{\tbmpar@tmp}{%
}{%
\expandafter\let\expandafter\tbmpar@currbox
\csname\tbmpar@tmp\endcsname
\unvbox\tbmpar@currbox
\tbmpar@FreeBox\tbmpar@currbox
\global\let\tbmpar@inuse=Y%
}%
}%
\ifx\tbmpar@inuse Y%
\splittopskip=\topskip
\setbox0=\vsplit\tbmpar@box to\z@
\boxmaxdepth=\maxdepth
\setbox\tbmpar@box=\vbox to\textheight{%
\unvbox\tbmpar@box
}%
\box\tbmpar@box
\fi
\endgroup
}%
}%
}
\makeatother
\begin{document}
%
% If you comment the next line, there is an additional error. If someone could
% solve this, help is appreciated. But currently that's not the main issue.
\topmarginpar{}
\begin{widefigure}[t]
\color{green}\rule{\linewidth}{2cm}
\caption{Top placement of figure, odd page.}
\end{widefigure}
\botmarginpar{Bottom margin note seems to be fine.}
\lipsum[2-5]
% Now we are on an even page
\topmarginpar{\lipsum[57]}
\botmarginpar{\lipsum[57]}
\lipsum[1-6]
% On an odd page, again
\begin{widefigure}[b]
\color{green}\rule{\linewidth}{2cm}
\caption{Bottom placement, odd page}
\end{widefigure}
\lipsum[1-3]
% Now we are on an even page!
\begin{widefigure}[t]
\color{red}\rule{\linewidth}{2cm}
\caption[A normal caption]{Top placement, even page. Figure vanished!}
\end{widefigure}
\lipsum
\begin{widefigure}[b]
\color{red}\rule{\linewidth}{2cm}
\caption[A normal caption]{Bottom placement, even page. Figure vanished!}
\end{widefigure}
\lipsum[1-12]
\end{document}
答案1
我修改了解决方案以包含标题。 \gettruepage 宏现在也返回 x,y 位置(以检查底部与顶部)。请注意,由于它使用辅助文件,因此需要运行两次才能正常工作。
\documentclass[paper=a4,11pt]{scrbook}
\usepackage[left=1in,top=1in,headsep=2\baselineskip,
textwidth=26pc,marginparsep=2pc,marginparwidth=12pc,
textheight=44\baselineskip,headheight=\baselineskip]{geometry}
% It took me a while to figure out the (x)color here is not merely used for
% providing color...
\usepackage{xcolor}
\usepackage{lipsum}
\usepackage{environ}% create an environment using \BODY
% The \gettruepage marcro returns the page number (as \truepage} in places where \thepage won't,
% such as inside floats or paragraphs split over 2 pages.
\pdfpageheight=\paperheight
\pdfpagewidth=\paperwidth
\newcounter{truepageindex}
\newcount{\truepage}% returns page
\newlength{\truex}% returns distance from left side of text area
\newlength{\truey}% returns distance from top of text area
\newcommand{\newtruepage}[4]% #1 = \thetruepageindex, #2 = \thepage, #3 = \pdflastxpos, #4 = \pdflastypos
{\global\expandafter\edef\csname truepage#1\endcsname{#2}%
\global\expandafter\edef\csname truex#1\endcsname{#3}%
\global\expandafter\edef\csname truey#1\endcsname{#4}}
\makeatletter
\newcommand{\gettruepage}{\stepcounter{truepageindex}%
\pdfsavepos
\protected@write\@auxout{}{\string\newtruepage{\thetruepageindex}{\thepage}
{\noexpand\number\pdflastxpos}{\noexpand\number\pdflastypos}}%
\@ifundefined{truepage\thetruepageindex}%
{\truepage=\c@page \truex=0pt \truey=0pt}%
{\truepage=\csname truepage\thetruepageindex\endcsname\relax
\truex=\csname truex\thetruepageindex\endcsname sp\relax
\truey=\csname truey\thetruepageindex\endcsname sp\relax
\truey=\dimexpr \paperheight-\truey-1in-\topmargin-\headheight-\headsep\relax
\advance\truex by -1in
\ifodd\truepage\relax\advance\truex by -\oddsidemargin
\else \advance\truex by -\evensidemargin
\fi}%
}%
\makeatother
% caption handler
\newif{\iffakecaption}
\newcommand{\fakecaptiontext}{}% reserve name
\makeatletter
\newcommand{\fakecaption}[2][\@empty]% #1 = short caption (optional), #2 = long caption
{\global\fakecaptiontrue
\refstepcounter{figure}%
\ifx#1\@empty\def\fakecaptiontext{#2}%
\else\def\fakecaptiontext{#1}%
\fi
\addcontentsline{lof}{figure}{\string\numberline {\thefigure}{\ignorespaces \fakecaptiontext}}%
\gdef\fakecaptiontext{#2}}
\makeatother
% widefigure environment
\newsavebox{\widefigurebox}
\newsavebox{\widefigurecaption}
\newlength{\widefiguretest}% compares middle of figure to middle of text area
\newlength{\widefigureup}% baseline to baseline for caption above
\newlength{\widefiguredown}% baseline to baseline for caption below
\newlength{\widefiguresize}% total height of figure plus caption plus extra \marginparpush
\newcount{\widefigurelast}% last page with figure on bottom
\NewEnviron{widefigure}[1][\empty]{%
\figure[#1]%
\let\oldcaption=\caption
\let\caption=\fakecaption
\fakecaptionfalse
\savebox{\widefigurebox}{\begin{minipage}{\dimexpr \textwidth+\marginparsep+\marginparwidth}%
\BODY\end{minipage}}%
\let\caption=\oldcaption
\settoheight{\widefigureup}{\usebox{\widefigurebox}}%
\settodepth{\widefiguredown}{\usebox{\widefigurebox}}%
\widefiguretest=\dimexpr .5\textheight-.5\widefigureup +.5\widefiguredown\relax
\advance\widefigureup by \marginparpush
\iffakecaption
\savebox{\widefigurecaption}{\parbox{\marginparwidth}%
{\raggedright\textbf{Figure \thefigure: }\fakecaptiontext}}%
\settodepth{\widefiguresize}{\usebox{\widefigurecaption}}%
\advance\widefigureup by \widefiguresize
\settoheight{\widefiguresize}{\usebox{\widefigurecaption}}%
\advance\widefiguredown by \widefiguresize
\advance\widefiguredown by \marginparpush
\fi
\gettruepage
\leavevmode% needed for \rlap and \llap
\ifodd\truepage\relax
\rlap{\usebox{\widefigurebox}}%
\iffakecaption
\ifdim\truey>\widefiguretest\relax
\rlap{\hspace{\textwidth}\hspace{\marginparsep}%
\raisebox{\widefigureup}[0pt][0pt]{\usebox{\widefigurecaption}}}%
\global\widefigurelast=\truepage
\else
\rlap{\hspace{\textwidth}\hspace{\marginparsep}%
\raisebox{-\widefiguredown}[0pt][0pt]{\usebox{\widefigurecaption}}}%
\fi
\fi
\else
\rlap{\hspace{-\marginparwidth}\hspace{-\marginparsep}\usebox{\widefigurebox}}%
\iffakecaption
\ifdim\truey>\widefiguretest\relax
\llap{\raisebox{\widefigureup}[0pt][0pt]{\usebox{\widefigurecaption}}%
\hspace{\marginparsep}}%
\global\widefigurelast=\truepage
\else
\llap{\raisebox{-\widefiguredown}[0pt][0pt]{\usebox{\widefigurecaption}}%
\hspace{\marginparsep}}%
\fi
\fi
\fi
\advance\widefigureup by \widefiguredown
\global\widefiguresize=\widefigureup
\endfigure}
\begin{document}
%
% If you comment the next line, there is an additional error. If someone could
% solve this, help is appreciated. But currently that's not the main issue.
%\topmarginpar{}
\begin{widefigure}[t]
\color{green}\rule{\linewidth}{2cm}% percent needed to prevent blank line at botttom
\caption{Top placement of figure, odd page.}\label{test}
\end{widefigure}
This is a label test for Figure \ref{test}.
The height of the figure plus caption is \the\widefiguresize.
\lipsum[2-5]
% Now we are on an even page
\lipsum[1-6]
% On an odd page, again
\begin{widefigure}[b]
\color{green}\rule{\linewidth}{2cm}%
\caption{Bottom placement, odd page}
\end{widefigure}
\lipsum[1-3]
% Now we are on an even page!
\begin{widefigure}[t]
\color{red}\rule{\linewidth}{2cm}%
\caption[A normal caption]{Top placement, even page. Figure vanished!}
\end{widefigure}
\lipsum
\begin{widefigure}[b]
\color{red}\rule{\linewidth}{2cm}%
\caption[A normal caption]{Bottom placement, even page. Figure vanished!}
\end{widefigure}
\lipsum[1-3]
\listoffigures
\end{document}
答案2
我找到了一个看似可以解决问题的方法。虽然它还不完整,而且出现了一些未满的框,但它或多或少满足了我的要求。间距似乎也不正确。
这个解决方案的目标是,我意识到(经过很长时间的尝试去理解 David 的代码)\@cflt
和\@cflb
会根据浮动的位置而扩展。David 使用它来定义不同的版本,\FS@junk
丢弃不需要的框,我用它来设置\vspace*
包含边距内容的框的顶部或底部的长度 d。
这种方法一直有效,直到同一页上出现两个浮点数,因为我只使用一个长度来存储浮点数的垂直尺寸,而第二个浮点数会直接覆盖该尺寸。此时,解决方案可能是利用相应的计数器(图形/表格)或引入新的计数器。
此外,我不再使用基于标签红色的机制来检测页面是偶数还是奇数,这不会导致对未定义标签的投诉(Herbert 的代码需要标签,因此需要运行两次,但第二次运行时没有警告)。
这是 MWE(同样很长,上面链接的两个代码片段都包括在内)。我在 David 的代码中添加了一些注释(就我所理解的而言),也许这可以帮助其他人更好地理解它。
\documentclass[paper=a4,11pt]{scrbook} \usepackage[T1]{fontenc} \usepackage[左=1 英寸,上=1 英寸,headsep=2\baselineskip, 文本宽度=26pc,边距解析=2pc,边距解析宽度=12pc, textheight=44\baselineskip,headheight=\baselineskip]{几何} \usepackage{xcolor,atbegshi,picture,zref-abspage,ragged2e} \usepackage{lipsum} \制作字母 % 这一魔法由 David Carlisle 发布在 TeX-SX 上: %http://tex.stackexchange.com/questions/56017/formatting-floats-differently-based-on-placement % % \@floatswitch-macro 需要 4 个参数,即浮点数的内容 % 应排版,如果位于顶部(#1)、底部(#2),在单个 % 页面(#3) 或此处(#4) % \def\@floatswitch#1#2#3#4{% %(猜测)这些行以某种方式处理计数器,以避免 %计数器增加了一以上。 \def\@elt##1{\global\value{##1}\the\value{##1}\relax}% \edef\FS@ckpt{\cl@@ckpt}% \让\@elt\放松 % 反向交易到此结束,但由 \FS@ckpt 使用 \hbox 到 3sp{% \vbox{{\FS@ckpt#1\par}}% \vbox{{\FS@ckpt#2\par}}% \vbox{{\FS@ckpt#3\par}}% \vbox{{\FS@ckpt#4\par}}% \hss}\aftergroup\break% } % % 这里,选择了正确的框。执行该任务的宏是 \FS@junk, % 扔掉那些没用到的盒子。 % \def\FS@checkswitch#1{%# \ifdim\wd#1=3sp % \setbox\z@\box#1% \开始组 \vbadness\maxdimen \setbox\z@\vsplit\z@ 改为 \textheight \setbox\z@\vbox{\unvbox\z@\global\setbox\@ne\lastbox}% \setbox\z@\vbox{\unvbox\@ne\unskip\global\setbox\@ne\lastbox}% \setbox\z@\hbox{\unhbox\@ne\unskip \FS@垃圾 \global\setbox\@ne\lastbox}% \结束组 \别的 \global\setbox\@ne\box#1% \fi} % 我不知道以下宏 \def\@comflelt#1{% \FS@检查开关#1% \setbox\@tempboxa \vbox{\unvbox\@tempboxa\box\@ne\vskip\floatsep}} % 显然(好吧,这只是一个有根据的猜测),\@cflt 用于浮点数 % 位于页面顶部。一旦我意识到这一点,我的问题是 %几乎解决了。 \让\保存@cflt\@cflt \def\@cflt{% \def\FS@垃圾{% % 由于浮动位于页面顶部,我们增加 % \tmbparTopSepLength 在框顶部获得一些空间 % 包含边距的内容 \setlength{\tbmparTopSepLength}{\baselineskip}% \addtolength{\tbmparTopSepLength}{\captionlength}% \addtolength{\tbmparTopSepLength}{\contentlength}% \global\tbmparTopSepLength=\tbmparTopSepLength \setbox\z@\lastbox\setbox\z@\lastbox\setbox\z@\lastbox}% \已保存@cflt} \let\FS@junk\relax % 这是(另一个合理的猜测)当浮点数为 % 放置在页面底部。使用方法与上述相同。 \让\保存@cflb\@cflb \def\@cflb{% \def\FS@垃圾{% \setlength{\tbmparBottomSepLength}{2\baselineskip}% \addtolength{\tbmparBottomSepLength}{\captionlength}% \addtolength{\tbmparBottomSepLength}{\contentlength}% \global\tbmparBottomSepLength=\tbmparBottomSepLength \setbox\z@\lastbox\setbox\z@\lastbox}% \已保存@cflb} % 同样,不知道。 \def\@helper#1\box\@currbox#2!!{% \def\@addtocurcol{% #1% \let\FS@junk\relax \FS@checkswitch\@currbox \box\@ne #2}}% \expandafter\@helper\@addtocurcol!! % 还是那句话,不知道。 \def\@wtryfc #1{% \全局\setbox\@outputbox\vbox{% \unvbox\@输出框 \vskip\@fpsep \def\FS@junk{\setbox\z@\lastbox}% \FS@检查开关#1% \box\@ne}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % 处理类似图形内容的环境 % \newsavebox{\@ContentCollectorBox} \newsavebox{\@CaptionCollectorBox} \newenvironment{@CollectContentAndCaption}[1][\linewidth]{% % 此环境将其内容收集在框 \@ContentCollectorBox 中, % 框的宽度由可选参数 #1 给出(默认为 % \行宽) % 此外,它重新定义 \caption 宏并将其内容保存在 % 宏 \@CurrCaptionLong 和 \@CurrCaptionShort。 % % 该框和两个宏在全球范围内可用。 \开始组 \开始{lrbox}{0\null\global\setbox\@ContentCollectorBox}% \开始{迷你页面}{#1}% \renewcommand\caption[2][]{% \gdef\@CurrCaptionLong{##2}% \ifx\\##1\\ \gdef\@CurrCaptionShort{##2}% \别的 \gdef\@CurrCaptionShort{##1}% \fi }% }{% \结束{迷你页面}% \结束{lrbox}% \结束组 } % % 提供一个在边缘延伸的浮动图形的环境。 % \newenvironment{宽图}[1][]{% % 存储可选参数。如果提供,请添加方括号。 \ifx\\#1\\ \def\@rgOne{}% \别的 \def\@rgOne{[#1]}% \fi % %启动上面定义的环境 \begin{@CollectContentAndCaption}[\dimexpr\textwidth+\marginparsep+\marginparwidth]% }{% % 结束环境 \结束{@CollectContentAndCaption}% \begin{lrbox}{\@CaptionCollectorBox}% \begin{minipage}{\marginparwidth}% \RaggedRight \@CurrCaptionLong \end{迷你页面} \结束{lrbox} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 这是解决方案的一部分(但也带来了新的问题) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 在这里我全局设置了两个包含垂直尺寸的长度 % 标题和内容 \setlength{\captionlength}{\ht\@CaptionCollectorBox}% \addtolength{\captionlength}{\dp\@CaptionCollectorBox}% \global\captionlength=\captionlength\relax \setlength{\contentlength}{\ht\@ContentCollectorBox}% \addtolength{\contentlength}{\dp\@ContentCollectorBox}% \全局\内容长度=\内容长度\放松 % 使用可选参数启动图形环境 % \begin{widefigure} 部分。我在这里使用 \figure 是为了避免 % \expandafter-orgy 扩展参数 \expandafter\figure\@rgOne % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 这也是新的。这里,一些未满的盒子仍然需要 % 已检查。 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \@floatswitch 是魔法内部的命令,我刚刚添加了 @ \@浮球开关{% \ifodd\c@page% \rlap{\usebox{\@ContentCollectorBox}}% \vbox 为 0pt{% \rlap{% \hspace*{\dimexpr\textwidth+\marginparsep}% \usebox{\@CaptionCollectorBox}% }% \vss } \别的 \rlap{\hspace*{\dimexpr-\marginparwidth-\marginparsep}\usebox{\@ContentCollectorBox}}% \vbox 为 0pt{% \llap{% \usebox{\@CaptionCollectorBox}% \hspace*{\marginparsep}% }% \vss }% \fi }{% % % 大致与上面相同,但位于底部。 % \ifodd\c@page% \vbox 为 0pt{% \vss \rlap{\hspace*{\dimexpr\textwidth+\marginparsep}% \usebox{\@CaptionCollectorBox}% }% \vspace*{\baselineskip}% }% \rlap{\usebox{\@ContentCollectorBox}}% \别的 \vbox 为 0pt{% \vss \llap{% \usebox{\@CaptionCollectorBox}% \hspace*{\marginparsep}% }% \vspace*{\baselineskip}% }% \rlap{\hspace*{\dimexpr-\marginparwidth-\marginparsep}\usebox{\@ContentCollectorBox}}% \fi }{% % 我还需要一些页面布局 % \@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}% }{% % 我不希望数字被放在这里。无论如何,我需要一个解决方案 % 这个也是。 % \@wide{\wd\@ContentCollectorBox}{\usebox{\@ContentCollectorBox}}% }% \结束图 } % % 这个魔术是由 Heiko Oberdiek 发布的 % http://tex.stackexchange.com/questions/69517/send-and-stack-marginpar-to-the-top-or-the-bottom-of-the-page \providecommand*{\c@zabspage}{\c@abspage} % 我定义了四个新的长度,用于在顶部留出空间, % tbmpar 节点的底部 \newlength\tbmparTopSepLength \newlength\tbmparBottomSepLength % 和两个保持包含标题的框的垂直尺寸 % 和浮点数的内容 \newlength\caption长度 \新长度\内容长度 % 在框顶部和底部扩展的两个命令包含 % 边距的内容 \newcommand*{\tbmparTopSep}{% \vspace*{\tbmparTopSepLength}% } \newcommand*{\tbmparBottomSep}{% \vspace*{\tbmparBottomSepLength}% } % 重置长度的宏 \新命令\restoreSeps{% \全局\tbmparTopSepLength0pt\放松%\@zp \全局\tbmparBottomSepLength0pt\放松 } \恢复Seps % 接下来几行是 Heiko 的代码 % * 用于配置的用户宏 % % \tbmparItemSep 插入到边注之间 % \tbmparMiddleSep 插入顶部和底部边注之间。 \newcommand*{\tbmparItemSep}{% \vspace{1ex 减 .5ex}% \hrule \vspace{1ex 减 .5ex}% } \newcommand*{\tbmparMiddleSep}{% \vspace*{0pt 加 1fil}% } % * 调试消息 % \newcommand*{\tbmparDebug}[1]{% \typeout{[tbmpar] #1}% } %* 标签管理以记住绝对页码 % % \tbmpar@PageByLabel 存储并加载绝对页码 % 标签并定义 \tbmpar@page 为绝对页码或 % 如果标签尚不可用,则为零。 \newcount\c@tbmpar@item \c@tbmpar@item\z@ \newcommand*{\tbmpar@PageByLabel}{% \全球\进步\c@tbmpar@item\@ne \zref@labelbyprops{tbmpar\the\c@tbmpar@item}{abspage}% \edef\tbmpar@page{% \zref@extractdefault{tbmpar\the\c@tbmpar@item}{abspage}{0}% }% \zref@refused{tbmpar\the\c@tbmpar@item}% \tbmparDebug{项目 \the\c@tbmpar@item\space 在页面 \tbmpar@page}% } %* 盒子登记管理 \newcount\c@tbmpar@box \c@tbmpar@box\z@ \let\tbmpar@boxfreelist\@empty % 从空闲列表中获取一个新的空闲盒子寄存器,或者 % 如果空闲列表为空,则分配一个新的盒子寄存器。 \newcommand*{\tbmpar@NextBox}[1]{% \@next#1\tbmpar@boxfreelist{% \tbmparDebug{重复使用的框:#1}% }{% \全球\进步\c@tbmpar@box\@ne \expandafter\newbox\csname tbmpar@box\the\c@tbmpar@box\endcsname \edef#1{\csname tbmpar@box\the\c@tbmpar@box\endcsname}% \tbmparDebug{新框:#1}% }% } % 将空闲的盒子放入空闲列表。 \newcommand*{\tbmpar@FreeBox}[1]{% \开始组 \让\@elt\放松 \xdef\tbmpar@boxfreelist{% \tbmpar@boxfreelist \@elt#1% }% \tbmparDebug{空闲框:#1}% \结束组 } \newsavebox{\tbmpar@box} % 每个 marginpar 被放入一个盒子中,该盒子被初始化为 % parbox/minipage。 \newcommand*{\tbmparBoxSetup}{} \newcommand{\tbmpar@VBox}[1]{% \vbox{% \颜色@begingroup \hsize\边距宽度 \edef\tbmpar@restore@ifminipage{% \如果@minipage \noexpand\@minipagetrue \别的 \noexpand\@minipagefalse \fi }% \@parboxrestore \@marginparreset \tbmparBox设置 #1% \tbmpar@restore@ifminipage \颜色@结束组 }% } % 宏 \tbmpar@marginpar 查找页边距注释 % 属于,将注释存储在一个框中,并将该框附加到 % 注释该页面的收集器寄存器。 % 每个页面分配一个盒子收集器寄存器,用于收集 % 高音符和一个收集低音符的音调。 % 盒子寄存器的名称是 \tbmpar@box。 \newcommand{\tbmpar@marginpar}[4]{% \ifh模式 \@bsphack \fi \tbmpar@PageByLabel \ifnum\tbmpar@page>\z@ \setbox\tbmpar@box\tbmpar@VBox{#4}% \@ifundefined{tbmpar@#1box\tbmpar@page}{% \tbmpar@NextBox\tbmpar@currbox \全局\expandafter\let \csname tbmpar@#1box\tbmpar@page\endcsname \tbmpar@currbox \global\setbox\tbmpar@currbox=\vbox{% \unvbox\tbmpar@box }% }{% \tbmparDebug{使用框:\tbmpar@currbox}% \expandafter\let\expandafter\tbmpar@currbox \csname tbmpar@#1box\tbmpar@page\endcsname \global\setbox\tbmpar@currbox\tbmpar@VBox{% \unvbox#3% \par \开始组 \tbmpar项目Sep \结束组 \unvbox#2% }% }% \fi \ifh模式 \@esphack \fi } \newcommand*{\topmarginpar}{% \tbmpar@marginpar{顶部}\tbmpar@currbox\tbmpar@box } \newcommand*{\botmarginpar}{% \tbmpar@marginpar{bot}\tbmpar@box\tbmpar@currbox } % 在发货时,我们寻找这个盒子收集器寄存器 % 页面,并将这些框设置在 marginpar 框中,并尊重 % \topskip 和 \maxdepth。 \def\@marginparxpos{0pt}\def\@marginparypos{0pt}% \AtBeginShipout{% \AtBeginShipoutUpperLeft{% % % 我添加了以下相应长度的定义,以便能够 % 区分奇数页和偶数页。 % \ifodd\c@page% \def\@marginparxpos{\dimexpr 1in+\oddsidemargin+\textwidth+\marginparsep\relax}% \def\@marginparypos{-\dimexpr 1in+\topmargin+\headheight+\headsep+\textheight\relax}% \别的 \def\@marginparxpos{\dimexpr 1in+\evensidemargin-\marginparsep-\marginparwidth\relax}% \def\@marginparypos{-\dimexpr 1in+\topmargin+\headheight+\headsep+\textheight\relax}% \fi \放(% \@marginparxpos,\@marginparypos% ){% \开始组 \global\let\tbmpar@inuse=N% \setbox\tbmpar@box=\tbmpar@VBox{% \惩罚-\@M % % 我在这里插入顶部的空格 % \tbmparTopSep \edef\tbmpar@tmp{tbmpar@topbox\the\value{zabspage}}% \@ifundefined{\tbmpar@tmp}{% }{% \expandafter\let\expandafter\tbmpar@currbox \csname\tbmpar@tmp\endcsname \unvbox\tbmpar@currbox \tbmpar@FreeBox\tbmpar@currbox \global\let\tbmpar@inuse=Y% }% \结束 \tbmpar中间九月 \edef\tbmpar@tmp{tbmpar@botbox\the\value{zabspage}}% \@ifundefined{\tbmpar@tmp}{% }{% \expandafter\let\expandafter\tbmpar@currbox \csname\tbmpar@tmp\endcsname \unvbox\tbmpar@currbox \tbmpar@FreeBox\tbmpar@currbox \global\let\tbmpar@inuse=Y% }% % % 在这里我在底部插入空格 % \tbmpar底部Sep }% \ifx\tbmpar@inuse Y% \splittopskip=\topskip \setbox0=\vsplit\tbmpar@box 到\z@ \boxmaxdepth=\maxdepth \setbox\tbmpar@box=\vbox 到\textheight{% \unvbox\tbmpar@box }% \box\tbmpar@box \fi \结束组 }% }% % 最后,长度被重置。 \恢复Seps } \makeatother \开始{文档} \lipsum[1] \topmarginpar{更长的前调!更长的前调!更长的前调!更长的前调!更长的前调!更长的前调!} \begin{宽图}[t] \color{绿色}\rule{\linewidth}{2cm} \caption{顶部有更长的标题!顶部有更长的标题!顶部有更长的标题!顶部有更长的标题!} \end{宽图} \botmarginpar{下边距位于底部。} \lipsum[2-5] % 现在我们处于偶数页 \botmarginpar{更长的底调!更长的底调!更长的底调!更长的底调!} \begin{宽图}[b] \color{绿色}\rule{\linewidth}{2cm} \caption{底部放置带有较长的标题。底部放置带有较长的标题。底部放置带有较长的标题。底部放置带有较长的标题。底部放置带有较长的标题。底部放置带有较长的标题。} \end{宽图} \lipsum[1-3] \begin{宽图}[t] \color{红色}\rule{\linewidth}{1cm} \caption{首先定义顶部标题。} \end{宽图} \topmarginpar{距离过大的顶音。} \botmarginpar{具有相同距离的底部音符(在这种情况下可以)。} \begin{宽图}[b] \color{红色}\rule{\linewidth}{2cm} \caption{底部标题,第二个定义,比顶部标题长 一。而且内容更长。} \end{宽图} \lipsum \结束{文档}