# Why is fixltx2e incompatible with tikzexternalize

I had some weird problems with tikzexternalize sometimes working sometimes not. I narrowed it down to the culprit fixltx2e. Here is a MWNE (Minimal not working exmple)

@ ALtermundus: Yes this is your picture (It is just too nice not to use it ;-)

\documentclass{article}

\usepackage{fixltx2e}

\usepackage{pgf}
\usepackage{tikz}
\usepackage{pgfplots}

\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize

\newcommand{\fancypicture}{
% from http://altermundus.com/pages/tikz/tikz-examples/index.html
\path  (0,0)       coordinate (A)
(-60:12cm) coordinate (B)
(240:12cm) coordinate (C);
\foreach \density in {10,20,...,160}
\draw[fill=blue!\density]
(A) coordinate  (X) -- (B) coordinate[pos=.15] (A) --
(C) coordinate[pos=.15] (B) --
(X) coordinate[pos=.15] (C);
}

\begin{document}

\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}

\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}

\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}

\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}

\end{document}


The weird thing with the code above: If only two pictures are inserted everything works. Only if more pictures are drawn, I suspect this triggers some fix in fixltx2e and externalization fails. Since this was quite hard to track down I just wanted to know if there are more such subtleties to expect with tikzexternalize or fixltx2e.

-

The problem seems to be in the fact that fixltx2e redefines \@doclearpage in a way that the doesn't please the externalize library: the output routine runs without producing any page and the compilation stops. This doesn't happen when only two figures are present because they fit on one page, I guess.

I don't think there is much else to do than not loading fixltx2e.

-

Update: This is now fixed in PGF CVS, see Christian Feuersänger's comment below.

When TikZ/PGF goes into externalising mode then it still processes the entire document. It needs to do this to ensure that it is in the right "state" when it gets to the picture that it is currently processing (ie any macros or styles or whatevers are as they would be in the normal document). This means that it still goes through the process of building pages and sorting floats, it just throws it all away at the last minute.

It does do a little bit of optimising. Anything in an \includegraphics can safely be thrown away. So also is any tikz picture that isn't the one being processed.

However, this has an unexpected side effect. It throws away the \includegraphics command or tikzpicture environment, but it doesn't throw away the containing float (which is sensible as that float can contain stuff other than the picture). If, though, the float did only contain the picture then it is now a box of zero height. This causes a problem when LaTeX tries to build a float page which consists entirely of these thrown away graphics (which, remember, could be other tikz pictures). And as TikZ does this for every graphic other than the one that is being externalised, this could happen quite easily.

The problem that this causes is that it is quite possible that the resulting float page is also of zero height. And this is a problem because LaTeX tests to see if the float page has non-zero height to check that it has been made correctly. If the float page was of zero height the assumption is that it failed somehow and all the floats have to be pushed onto the next float page. But if the floats themselves are of zero height we can never get out of this loop.

The reason that fixltx2e makes this evident is that it adds a loop to ensure that all the floats are correctly processed (before, if this failed it would simply lose those floats - I assume, I'm no expert on this).

This suggests a number of options:

1. Disable the loop in \@doclearpage. This is the line \ifx\@deferlist\@empty \else\clearpage \fi.
2. Disable the optimisation step in tikz's externalisation library. This means putting the option \tikzset{external/optimize=false} in your preamble. This is probably the safest but might make the externalisation step slower.
3. Allow zero-height float pages. This involves redefining the test as follows:

\def\@ytryfc #1{%
\begingroup
\gdef\@flsucceed{\@elt #1}%
\global\let\@flfail\@empty
\@tempdima\ht #1%
\let\@elt\@ztryfc
\@trylist
\ifdim \@tempdima <\@fpmin
\@cons\@failedlist #1%
\else
\fi
\endgroup
\let\@elt\@gobble
\fi}

4. Fix the TikZ/PGF optimisation of tikzpicture so that it creates a box of non-zero height. (I tried this but couldn't come up with something that was guaranteed to work.)

5. Add \newpage after every externalised float. This means that it doesn't end up making a float page. This is a bit extreme, except that you can put it in \tikzifexternalizing to ensure that it only happens in the externalisation run.

Now, I'd only recommend making changes to the Deep Core in the externalising run. Fortunately, TikZ provides the \tikzifexternalizing command, so put the redefinitions in there (surrounding the whole lot with \makeatletter ... \makeatother) if you don't want to lose the optimisations.

-
Very interesting analysis. –  egreg Mar 14 '13 at 11:44
@egreg I lost the first version of this post and forgot in the second to say that your answer gave me the starting point. Without that, I'd've never figured out where to look. –  Loop Space Mar 14 '13 at 11:58
I have just committed a bugfix to PGF CVS which solves the problem. Interestingly, it required not just dummy text in images which have been optimized away, but right after that image which is currently being externalized. Thanks for the good analysis! –  Christian Feuersänger Mar 14 '13 at 23:11
@ChristianFeuersänger Great! That last bit might explain why my attempt to add dummy text didn't work. –  Loop Space Mar 15 '13 at 9:12