出力ルーチンに変更を加えた後、偶数ページに図の内容が表示されない

出力ルーチンに変更を加えた後、偶数ページに図の内容が表示されない

広い余白のある文書では、marginpar 領域にまで広がる図の環境を提供したいと考えています。さらに、図の配置に応じて、キャプション テキストもこの領域に、図の上または下に配置するようにしたいと考えています。さらに、これは偶数ページと奇数ページで機能するはずです (scrbook私の場合は を使用していますが、twosideオプションでも同じ効果が得られます)。

私が最終的に達成したいことは、次の図でよく示されるでしょう (Inkscape で非常に素早く描いたもので、サイズの違いは気にしません)。

ここに画像の説明を入力してくださいここに画像の説明を入力してくださいここに画像の説明を入力してください

まず、\cite-macros から参照を収集し、下部の余白に出力したいと思います (これは機能しているため、MWE には表示されません)。幅の広い図の場合は、余白にもキャプションが表示されます。幅の広い図が下部にある場合は、参照を余白の図のキャプションの上に表示します。上部の余白にも出力されるものがある可能性があります。図からわかるように、twosideモードでは機能するはずです。

フィギュアがどこに配置されているかを検出するには、 David Carlisle が提案したコードキャプションをページの下部または上部の余白に配置するには、Heiko Oberdiek が提案したコード現在のページが奇数か偶数かをテストするには、\ifthispageoddから を使用しKOMA-Script、図が外側の余白まで拡張されていることを確認するには、addmargin*から の環境を使用します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 位置も返すようになりました (下と上を確認するため)。aux ファイルを使用するため、正しく機能するには 2 回実行する必要があることに注意してください。

\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がフロートの位置に応じて拡張されることに気付いたことです。David はこれを使用して、不要なボックスを破棄する\@cflbのさまざまなバージョンを定義し、私はこれを使用して、余白のコンテンツを含むボックスの上部または下部に d の長さを設定します。\FS@junk\vspace*

これは、フロートの垂直方向の寸法を格納するために 1 つの長さのみを使用し、2 番目のフロートによって単純に上書きされるため、同じページに 2 つのフロートが表示されるまで機能します。ここでの解決策は、それぞれのカウンター (図/表) を使用するか、新しいカウンターを導入することです。

さらに、ページが偶数か奇数かを検出するためにラベル赤ベースのメカニズムを使用しなくなったため、未定義のラベルに関する苦情は発生しなくなりました (Herbert のコードにはラベルが必要なので 2 回実行する必要がありますが、2 回目の実行では警告は発生しません)。

これが MWE です (これも長いですが、上にリンクされている両方のコード スニペットが含まれています)。David のコードにいくつかコメントを追加しました (私が理解している限り)。他の人が理解しやすくなるかもしれません。

\documentclass[paper=a4,11pt]{scrbook}
\usepackage[T1]{フォント}
\usepackage[left=1in,top=1in,headsep=2\baselineskip,
  テキスト幅=26pc、マージンパース幅=2pc、マージンパース幅=12pc、
  textheight=44\baselineskip,headheight=\baselineskip]{ジオメトリ}

\usepackage{xcolor,atbegshi,picture,zref-abspage,ragged2e}
\usepackage{リップサム}
\手紙を作る

% このマジックは David Carlisle によって TeX-SX に投稿されました:
% http://tex.stackexchange.com/questions/56017/formatting-floats-differently-based-on-placement


%
% \@floatswitchマクロは、フロートの内容である4つの引数を必要とします
% 上部 (#1)、下部 (#2)、単一行に配置する場合にタイプセットするべきもの
% ページ(#3) またはここ(#4)
%

\def\@floatswitch#1#2#3#4{%
  % (推測) これらの行は、何らかの方法でカウンターを処理し、
  % カウンターが 1 以上増加します。
  \def\@elt##1{\global\value{##1}\the\value{##1}\relax}%
  \edef\FS@ckpt{\cl@@ckpt}%
  \let\@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@チェックスイッチ#1{%#
  \ifdim\wd#1=3sp %
    \setbox\z@\box#1%
    \begingroup
      \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}%
    \endgroup
  \それ以外
    \global\setbox\@ne\box#1%
  \fi}


% 次のマクロについては分かりません

\def\@comflelt#1{%
  \FS@チェックスイッチ#1%
  \setbox\@tempboxa
     \vbox{\unvbox\@tempboxa\box\@ne\vskip\floatsep}}

% 明らかに(まあ、これは単なる推測ですが)、\@cfltはfloat型の場合に使用されます
%はページの上部に配置されています。これに気付いたとき、私の問題は
% ほぼ解決しました。

\let\保存しました@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\リラックス

% これは(別の推測ですが)フロートが
% はページの下部に配置されます。使用される方法は上記と同じです。
\let\保存しました@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\リラックス
    \FS@チェックスイッチ\@currbox
    \ボックス\@ne
    #2}}%

\expandafter\@helper\@addtocurcol!!

% また、わかりません。

\def\@wtryfc #1{%
  \global\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。
  %
  % ボックスと 2 つのマクロはグローバルに使用できます。
  \begingroup
    \begin{lrbox}{0\null\global\setbox\@ContentCollectorBox}%
      \begin{ミニページ}{#1}%
        \renewcommand\caption[2][]{%
           \gdef\@CurrCaptionLong{##2}%
           \ifx\\##1\\
             \gdef\@CurrCaptionShort{##2}%
           \それ以外
             \gdef\@CurrCaptionShort{##1}%
           \fi
        }%
}{%
      \end{ミニページ}%
    \end{lrbox}%
  \endgroup
}

%
% 余白に広がる浮動図形を提供する環境。
%
\newenvironment{widefigure}[1][]{%
  % オプションの引数を保存します。指定する場合は、角括弧で囲みます。
  \ifx\\#1\\
    \def\@rgOne{}%
  \それ以外
    \def\@rgOne{[#1]}%
  \fi
  %
  % 上記で定義した環境を起動します
  \begin{@CollectContentAndCaption}[\dimexpr\textwidth+\marginparsep+\marginparwidth]%
}{%
  % 環境を終了する
  \end{@CollectContentAndCaption}%
  \begin{lrbox}{\@CaptionCollectorBox}%
    \begin{ミニページ}{\marginparwidth}%
      \不揃い
      \@現在のキャプション長
    \end{ミニページ}
  \end{lrbox}
  % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % これは解決策の一部です(そして新たな問題を引き起こします)
  % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % ここでは、垂直方向の寸法を含む2つの長さをグローバルに設定します。
  % キャプションとコンテンツ
  \setlength{\captionlength}{\ht\@CaptionCollectorBox}%
  \addtolength{\captionlength}{\dp\@CaptionCollectorBox}%
  \global\captionlength=\captionlength\relax
  \setlength{\contentlength}{\ht\@ContentCollectorBox}%
  \addtolength{\contentlength}{\dp\@ContentCollectorBox}%
  \global\contentlength=\contentlength\relax
  % オプション引数で図環境を開始します
  % \begin{widefigure}の部分。ここでは\figureを使って、
  % \expandafter-orgy で引数を展開する
  \expandafter\図\@rgOne
  %
  % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % これも新しいものです。ここでは、まだ解決が必要な、不足しているボックスがいくつか発生しています。
  % 検査済み。
  % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % \@floatswitchはマジック内のコマンドです。@を追加しました。
    \@floatswitch{%
      \ifodd\c@ページ%
        \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@ページ%
        \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}}%
    }%
  \endfigure
}


%
% このマジックは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}

% 上部にスペースを残すために使用される4つの新しい長さを定義します。
% tbmpar-node の下部

\newlength\tbmparTopSepLength
\newlength\tbmparBottomSepLength

% と、キャプションを含むボックスの垂直寸法を維持する 2 つ
浮動小数点数の%と内容
\新しい長さ\キャプションの長さ
\新しい長さ\コンテンツの長さ

% ボックスの上部と下部に展開される2つのコマンド
% 余白の内容
\newcommand*{\tbmparTopSep}{%
  \vspace*{\tbmparTopSepLength}%
}
\newcommand*{\tbmparBottomSep}{%
  \vspace*{\tbmparBottomSepLength}%
}

% 長さをリセットするマクロ
\newcommand\restoreSeps{%
  \global\tbmparTopSepLength0pt\relax%\@zp
  \global\tbmparBottomSepLength0pt\relax
}
\復元セプス

% 次の行は再びHeikoのコードです

% * 設定用のユーザーマクロ
%
% \tbmparItemSep は欄外の注釈の間に挿入されます
% \tbmparMiddleSep は上部と下部の余白の注釈の間に挿入されます。

\newcommand*{\tbmparItemSep}{%
  \vspace{1ex マイナス .5ex}%
  \ルール
  \vspace{1ex マイナス .5ex}%
}

\newcommand*{\tbmparMiddleSep}{%
  \vspace*{0pt プラス 1fil}%
}
% * デバッグメッセージ
%
\newcommand*{\tbmparDebug}[1]{%
  \typeout{[tbmpar] #1}%
}

% * 絶対ページ番号を記憶するラベル管理
%
% \tbmpar@PageByLabelは絶対ページ番号を保存し、読み込みます。
% ラベルと絶対ページ番号で\tbmpar@pageを定義するか、
ラベルがまだ利用できない場合は % ゼロ。

\newcount\c@tbmpar@item
\c@tbmpar@アイテム\z@

\newcommand*{\tbmpar@PageByLabel}{%
  \global\advance\c@tbmpar@item\@ne
  \zref@labelbyprops{tbmpar\the\c@tbmpar@item}{abspage}%
  \edef\tbmpar@ページ{%
    \zref@extractdefault{tbmpar\the\c@tbmpar@item}{abspage}{0}%
  }%
  \zref@refused{tbmpar\the\c@tbmpar@item}%
  \tbmparDebug{ページ \tbmpar@page の項目 \the\c@tbmpar@item\space}%
}

% * ボックスレジスタ管理

\newcount\c@tbmpar@ボックス
\c@tbmpar@ボックス\z@

\let\tbmpar@boxfreelist\@空

% フリーリストから新しいフリーボックスレジスタを取得するか、
% フリーリストが空の場合は、新しいボックスレジスタを割り当てます。
\newcommand*{\tbmpar@NextBox}[1]{%
  \@next#1\tbmpar@boxfreelist{%  
    \tbmparDebug{再利用されたボックス: #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{新しいボックス: #1}%
  }%
}
% 空きボックスを空きリストに入れます。
\newcommand*{\tbmpar@FreeBox}[1]{%
  \begingroup
    \let\@elt\リラックス
    \xdef\tbmpar@boxfreelist{%
      \tbmpar@boxfreelist
      \@elt#1%
    }%
    \tbmparDebug{空きボックス: #1}%
  \endgroup
}

\newsavebox{\tbmpar@box}

% 各marginparは次のように初期化されたボックス内に配置されます。
% パーボックス/ミニページ。
\newcommand*{\tbmparBoxSetup}{}
\newcommand{\tbmpar@VBox}[1]{%
  \vbox{%
    \color@begingroup
    \hsize\marginparwidth
    \edef\tbmpar@restore@ifminipage{%
      \if@ミニページ
        \noexpand\@minipagetrue
      \それ以外
        \noexpand\@minipagefalse
      \fi
    }%   
    \@parboxrestore
    \@marginparreset
    \tbmparBox セットアップ
   #1%
    \tbmpar@restore@ifminipage
    \color@endgroup
  }%
}   

% マクロ \tbmpar@marginpar は余白の注釈があるページを検索します
%が属するボックスにメモを保存し、そのボックスを  
ページの% ノートコレクターレジスタ。
% 各ページには、収集するボックスコレクタレジスタが割り当てられています
% 上の音符を収集するレジスターと、下の音符を収集するレジスター。
% ボックスレジスタの名前は \tbmpar@box です。
\newcommand{\tbmpar@marginpar}[4]{%
  \ifhモード
    \@bsphack
  \fi
  \tbmpar@ラベル別ページ
  \ifnum\tbmpar@ページ>\z@
    \setbox\tbmpar@box\tbmpar@VBox{#4}%
    \@ifundefined{tbmpar@#1box\tbmpar@ページ}{%
      \tbmpar@NextBox\tbmpar@currbox
      \global\expandafter\let
          \csname tbmpar@#1box\tbmpar@page\endcsname
          \tbmpar@currbox
      \global\setbox\tbmpar@currbox=\vbox{%
        \unvbox\tbmpar@ボックス
      }%
    }{%
      \tbmparDebug{ボックスを使用: \tbmpar@currbox}%
      \expandafter\let\expandafter\tbmpar@currbox
          \csname tbmpar@#1box\tbmpar@page\endcsname
      \global\setbox\tbmpar@currbox\tbmpar@VBox{%   
        \unvbox#3%
        \パー
        \begingroup
          \tbmparアイテムSep
        \endgroup
        \unvbox#2%
      }%
    }%  
  \fi   
  \ifhモード
    \@エスファック
  \fi
}

\newcommand*{\topmarginpar}{%
  \tbmpar@marginpar{top}\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@ページ%
      \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%
    ){%
      \begingroup
        \global\let\tbmpar@inuse=N%
        \setbox\tbmpar@box=\tbmpar@VBox{%
          \ペナルティ-\@M
          %
          % ここで先頭にスペースを挿入します
          %
          \tbmparトップSep
          \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
          \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下9
        }%  
        \ifx\tbmpar@使用しない Y%
          \splittopskip=\topskip
          \setbox0=\vsplit\tbmpar@ボックスを\z@
          \boxmaxdepth=\maxdepth
          \setbox\tbmpar@box=\vbox から\texheight{%
            \unvbox\tbmpar@ボックス
          }%
          \box\tbmpar@box
        \fi
      \endgroup
    }%
  }%  
  % 最後に長さがリセットされます。
  \復元セプス
}     

\他のものを作る
\begin{ドキュメント}
\lipsum[1]
\topmarginpar{トップノートをもっと長く!トップノートをもっと長く!トップノートをもっと長く!トップノートをもっと長く!トップノートをもっと長く!トップノートをもっと長く!}
 \begin{widefigure}[t]
   \color{green}\rule{\linewidth}{2cm}
   \caption{上部に長いキャプションを!上部に長いキャプションを!上部に長いキャプションを!上部に長いキャプションを!}
 \end{ワイド図}
\botmarginpar{下余白は下にあります。}
\lipsum[2-5]
% これでページは揃いました
\botmarginpar{下の音符をもっと長く!下の音符をもっと長く!下の音符をもっと長く!下の音符をもっと長く!}
\begin{widefigure}[b]
  \color{green}\rule{\linewidth}{2cm}
  \caption{キャプションが長い場合は下部に配置します。キャプションが長い場合は下部に配置します。キャプションが長い場合は下部に配置します。キャプションが長い場合は下部に配置します。}
\end{ワイド図}
\lipsum[1-3]

\begin{widefigure}[t]
  \color{赤}\rule{\linewidth}{1cm}
  \caption{最初に定義されるトップキャプション。}
\end{ワイド図}
\topmarginpar{トップノートの距離が大きすぎる。}
\botmarginpar{同じ距離の一番下の音符(この場合は OK)。}
\begin{widefigure}[b]
  \color{赤}\rule{\linewidth}{2cm}
  \caption{2番目に定義される下部のキャプション。これは上部のキャプションよりも長い
    一つです。内容も長くなります。
\end{ワイド図}
\lipsum
\end{ドキュメント}

関連情報