14

I'm interested in changing how floats are formatted depending on whether they are placed at the top, bottom, or middle of a page, or on a float page. One package I am aware of that does something like this is tufte-latex, which places hanging captions in the margin below full-width figures if the figures are at the top or middle, but above if the figures are at the bottom. Looking at the code for tufte-latex, though, this is a pretty rudimentary check (as near as I can tell, the caption is placed on top exactly when the only placement specifier is "b"). And when the floats are put on a float page, the hanging captions don't look right.

Ideally, I'd like to be able to tell where a float has actually been placed and do something like

\if \finalfloatplacement t%
  % hang caption in margin below float
\fi
\if \finalfloatplacement h%
  % same as 't'; hang caption in margin below float
\fi
\if \finalfloatplacement b%
  % hang caption in margin above float
\fi
\if \finalfloatplacement p%
  % center caption below float
\fi

Presumably this would take a couple of LaTeX runs to iron out the positions.

3
  • the output routine provides no information about where it is placing a float, so the output routine would need to be hacked to provide that in (some sort of) label structure: hacking the or is a non-trivial operation... (not something i would even recommend; and note that latex 3's output routine is likely to be very different.) Commented May 16, 2012 at 10:36
  • Please see tex.stackexchange.com/questions/56673/…
    – yannisl
    Commented Dec 17, 2012 at 13:03
  • see also tex.stackexchange.com/q/523545/1090 Commented Jan 9, 2020 at 13:45

1 Answer 1

10

You have to dig fairly deep into LaTeX internals for this but it is possible for the figure to be saved four times (set for t b p h float areas respectively) and then the output routine pick the box it needs.

In the version here I have not redefined the whole output routine, so while it does pick the correct box (I hope) various arts of the output routine that test measurements are not redefined. This means that when measuring they will see a box that contains all of the four choices side by side, so it will have height the maximum height. This is probably OK unless the settings are very different. In the example the settings just differ in wording slightly and in colour.

the \floatswitch command that this defines must be the only thing in the float, otherwise things will go wrong.

enter image description here

\documentclass{article}
\usepackage{color}
\def\a{One two three four five six. }
\def\b{Apple, Pear, Banana, Orange. }
\def\c{\a\a\b\par\b\b\b\a\b\par\b\b\b\par}

\makeatletter

\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}


\tracingonline2
\showboxdepth1
\showboxbreadth25
\errorcontextlines\maxdimen

\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\foo#1\box\@currbox#2!!{%
\def\@addtocurcol{%
#1%
\let\FS@junk\relax
\FS@checkswitch\@currbox
\box\@ne
#2}}%
\expandafter\foo\@addtocurcol!!

\def\@wtryfc #1{%
  \global\setbox\@outputbox\vbox{%
    \unvbox\@outputbox
    \vskip\@fpsep
\def\FS@junk{\setbox\z@\lastbox}%
\FS@checkswitch#1%
\box\@ne}}

\makeatother
\begin{document}

\c

\def\fig#1{%
\begin{figure}#1
\floatswitch{%
\color{red}\centering\fbox{$\frac{1}{2}$}
\caption{t floats are red}}
{%
\color{blue}\centering\fbox{$\frac{1}{2}$}
\caption{b floats are blue}}
{%
\color{green}\centering\fbox{$\frac{1}{2}$}
\caption{p floats are green}}
{%
\color{yellow}\centering\fbox{$\frac{1}{2}$}
\caption{h floats are yellow}}
\end{figure}%
}
\fig{}
\c
\fig{[!h]}
\fig{[b]}
\c
\fig{[p]}
\begin{figure}
\centering
\fbox{NO SWITCH}
\caption{no switch}
\end{figure}
\c

\end{document}
6
  • Where in this code is the specific decision of which box is chosen; as I would have to replace it with an if@firstcolumn/ifoddpage selector instead of the tbp?
    – Suthek
    Commented Jan 9, 2020 at 13:03
  • @Suthek you could use the same mechanism (I think there may be another example from on this site) that saved twice as many boxes for left and right (or just two if you only care about that and not top/bottom) as it is it saves 4 and then for example \def\@cflt{% \def\FS@junk{\setbox\z@\lastbox\setbox\z@\lastbox\setbox\z@\lastbox}% \saved@cflt} defines \@cflt to extract the top box and \@cfltb extracts the bottom, they are the existing functions in the latex output routine that position top or bottom floats respectively, but here modified to take the correct part of the float box. Commented Jan 9, 2020 at 13:34
  • Hm, I'll have to look into that a bit more. Do you know of a good source where I can dive into the whole algorithm and what all the vars and functions (over)written here do and how they interact?
    – Suthek
    Commented Jan 9, 2020 at 13:41
  • texdoc source2e the documented latex sources. (Users really aren't supposed to go here:-) However if you really want just left/right I may re-open your question and just reference this rather than mark as duplicate as this isn't directly going to help (although the same principle will work) Commented Jan 9, 2020 at 13:44
  • TBF, I've been sitting on this new class for half a month now, so I'm not sure if I still fall under the "user" classfication. :) And learning more about TeX is always neat. If you want, I can edit my question to make it clearer what I'm trying to achieve before you decide to reopen it?
    – Suthek
    Commented Jan 9, 2020 at 14:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .