Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am busy developing some code to draw layouts. Part of the code overlays the layout as shown in the images below:

enter image description hereenter image description here

The black arrows to the side of the images, denote the \topfraction and \bottomfraction, parameters. It will be nice to only show them, if a float exists in that position. Is it possible to detect a float and its position?

(Aim of the package, is to show in one glance all the geometry parameters and also draw a grid, see the thin light teal lines).

share|improve this question
    
fancyhdr has some code for detecting floats, including an \iffloatpage macro that might be helpful. –  Alan Munn May 20 '12 at 21:41
    
@AlanMunn Thanks will have a look. –  Yiannis Lazarides May 21 '12 at 2:43
    
@AlanMunn Your suggestion worked well, if you want to add a line or two, I will accept it as an answer, otherwise will accept David's for his explanation. –  Yiannis Lazarides May 21 '12 at 17:50
    
Yiannis: since I assumed you were looking for code rather than a package solution, I'll leave it to David's expertise. –  Alan Munn May 21 '12 at 18:17

2 Answers 2

up vote 10 down vote accepted

within the output routine (which is where I assume you are adding your overlay) you could examine

    \@freelist     : List of empty boxes for placing new floats.
    \@toplist      : List of floats to go at top of current column.
    \@midlist      : List of floats in middle of current column.
    \@botlist      : List of floats to go at bottom of current column.
    \@deferlist    : List of floats to go after current column.
    \@dbltoplist   : List of double-col. floats to go at top of current
                     page.
    \@dbldeferlist : List of double-column floats to go on subsequent
                     pages.

Or you may prefer to patch

%  \begin{macro}{\@flupdates}
% \changes{v1.0f}{1993/12/05}{Command added}
%    This updates everything when a float is placed.
%
%    \begin{macrocode}
%<*2ekernel|autoload>
\def \@flupdates #1#2#3{%
   \global \advance #1\m@ne
   \global \advance \@colnum \m@ne
   \@tempdima -\ht\@currbox
   \advance \@tempdima
     -\ifx #3\@empty \textfloatsep \else \floatsep \fi
   \global \advance #2\@tempdima
   \global \advance \@colroom \@tempdima
   \@cons #3\@currbox
}

so that it updates your data structures in addition to the output routine internals.


Looking at fancyhdr. It uses the first method I suggested. For example it saves \@toplist (in \topfloat) before latex sets the column so that it is still defined at the point that the header is set. Then \iftopfloat does a simple ifx test to see if this is empty.

However if it is not empty then it is a list of (indexes of) box registers that hold the floats that were put at the top of the column. So you can tell how many floats are in that area by the length of the list. However you can't get the extent because by the time the header is called the floats have already been added and the float boxes cleared and recycled.

So this document (which doesn't load any package but uses relevant fancyhdr definitions) can test if there are any top floats and if so count the list and report how many floats are there (0 1 and 2 in this document) but when it iterates over the list to report the sizes of the floats it gets nothing as the boxes have been cleared.

\documentclass{article}

\setlength\textheight{20\baselineskip}
\raggedbottom

\makeatletter
\newif\iffootnote
\let\latex@makecol\@makecol
\def\@makecol{\ifvoid\footins\footnotetrue\else\footnotefalse\fi
\let\topfloat\@toplist\let\botfloat\@botlist\latex@makecol}
\def\iftopfloat#1#2{\ifx\topfloat\empty #2\else #1\fi}
\def\ifbotfloat#1#2{\ifx\botfloat\empty #2\else #1\fi}
\def\iffloatpage#1#2{\if@fcolmade #1\else #2\fi}

\def\ps@foo{%
\def\@oddhead{%
T: \iftopfloat{yes
               [{\count@\z@ \def\@elt{\advance\count@\@ne}\topfloat \the\count@}]%
               [{\def\@elt{, \the\ht}\topfloat}]%
}
{no}\hfill}}
\pagestyle{foo}

\makeatother

\def\a{One two three. }
\def\b{Red, Green, Blue. }
\def\c{\a\a\b\b\a\a\a\b\b\b\a}
\def\d{\c\c\par\a\b\c\b\par}

\begin{document}

\d

\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}

\d
\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}
\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}

\d
\end{document}

So instead of just using \let to save a snapshot of the latex lists use \edef to save a list which saves the height width and depth of the box. then in the page header you can count the list as before or add up all the heights (plus \floatsep for all but the first) and so report the height of the top float area.

Doing the same for the other areas is left as an exercise:-)

\documentclass{article}

\setlength\textheight{20\baselineskip}
\raggedbottom

\makeatletter
\newif\iffootnote
\let\latex@makecol\@makecol
\def\@makecol{\ifvoid\footins\footnotetrue\else\footnotefalse\fi
\def\@elt##1{\noexpand\@elt{\the\ht##1}{\the\dp##1}{\the\wd##1}}%
\edef\topfloat{\@toplist}%
\let\@elt\relax
\let\botfloat\@botlist\latex@makecol}

\def\iftopfloat#1#2{\ifx\topfloat\empty #2\else #1\fi}
\def\ifbotfloat#1#2{\ifx\botfloat\empty #2\else #1\fi}
\def\iffloatpage#1#2{\if@fcolmade #1\else #2\fi}

\def\count@elt#1#2#3{\advance\count@\@ne}
\def\sum@elt#1#2#3{\advance\dimen@\floatsep\advance\dimen@#1\relax}
\def\ps@foo{%
\def\@oddhead{%
T: \iftopfloat{yes
               [{\count@\z@ \let\@elt\count@elt \topfloat \the\count@}]%
               [{\dimen@-\floatsep \let\@elt\sum@elt \topfloat size of top area: \the\dimen@}]%
}
{no}\hfill}}
\pagestyle{foo}

\makeatother

\def\a{One two three. }
\def\b{Red, Green, Blue. }
\def\c{\a\a\b\b\a\a\a\b\b\b\a}
\def\d{\c\c\par\a\b\c\b\par}

\begin{document}

\d

\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}

\d
\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}
\begin{figure}[!t]
\fbox{XXXXXX}
\caption{jjj}
\end{figure}

\d
\end{document}
share|improve this answer
    
Thanks! I basically hook into the header with a ps@ definition that includes the tikz code (rather than the traditional picture put commands). Alan suggested the \iffloatpage etc from fancyhdr. These worked well but I can't seem to figure where the package hooks. I would appreciate it if you maybe have a look and add a comment or two on the mechanics. –  Yiannis Lazarides May 21 '12 at 17:44
    
just looked at fancyhdr, too long for a comment will add to answer –  David Carlisle May 21 '12 at 21:15

Based on Alan Munn's comment, I tried the conditionals from fancyhdr. These worked well. There are three conditionals, \iftopfloat, \ifbottomfloat, \iffloatpage.

To conditionally draw the line using TikZ,

\iftopfloat{%
\draw [dim,|<->|] (1in+\innermargin-0.3cm, \paperheight-1in-\topmargin-\headheight-\headsep)-- ++(0,-\topfraction\textheight) node[left,text width=1.5cm,text ragged] at ++ (0,0.4\textheight) {top\\ fraction\\ \topfraction}}{};
\draw[dim,|-|] ( (1in+\innermargin+0.3cm,\paperheight-1in-\topmargin-\headheight-\headsep-\topfraction\textheight) -- ++(0,-\textfloatsep);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.