The following code seems to work under extremely minimal testing (i.e., onesided, single column, and without colors only). It's a pretty huge hack though. I'm definitely open to better ways to do this or improvements on this code.
There are two parts to the code. The first is a new floating environment, sort of.
\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
}
That code redefines \@caption so that it typesets the caption inside a \vbox. (I'm not sure if the color stuff is needed or not. It doesn't seem to hurt, at least when colors aren't used.)
Then, rather than ending the float with \end@float, it ends the box started by \@xfloat—which is usually done by \end@float, hence setting it to \relax. If the caption box is not void, the current float box \@currbox is redefined to be a \vbox consisting of 3 items: the floating material in the original \@currbox, the caption box which has height 0 and depth 1sp and a skip of -1sp. Finally, we set the height of the box to the \textheight so that the output routine will stick the float on a page by itself when it is actually building pages.
Finally, \end@float will actually call the output routine twice which will cause the float to go onto the defer list, but no pages will actually be built and output here.
The second part of the code is a modification to the output routine. When actually producing pages of output, the lists of floats will be processed, one at a time. Since the box has the maximum height to fit on a page, it will be placed by itself. In particular, \@wtryfc will be executed for each box in the list of boxes that will fit on the page. Normally, it just adds its argument (the box) and some space to the \@outputbox.
This code hijacks that and calls my own routine if the height of the output box is 0 (this is just an optimization).
\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 needs to check that its argument is one of these special boxes. It does this by unboxing the box, checking that the last skip is -1sp and that the box before that has depth 1sp. If it does, then it is unboxed and saved. Finally, the only remaining box (the first box in the argument to \@wtryfc) is the original figure box, so save that.
\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
}
After looking for the \vbox{figure}\vbox{caption}\vskip-1sp in the \setbox, if no caption box was discovered, then it uses LaTeX's normal \@wtryfc to add the box to \@outputbox. Otherwise, a box corresponding to the facing caption page is constructed in \@outputbox. The special page style conditional is saved (this might be unnecessary, I'm not sure) and then the page style commands for the facingcaption page style are executed (\thispagestyle{facingcaption} doesn't work with \AtBeginShipout used by the showframes package since the margins need to change). Next, the page it actually output using \@outputpage. The \@outputbox is cleared and the normal \@wtryfc is executed for the figure box.
;-)). – Hendrik Vogt Jan 03 '11 at 18:59