3

I am trying to have a listing inside an animate environment. However I can't manage to do it if the hyperref package is loaded.

This is a MWE, obviously in the real application I need hyperref for other parts of the document. Is there a workaround? Some option in hyperref for example?

\documentclass{article}
\usepackage{animate}
\usepackage{listings}
\usepackage{hyperref} % comment this line to make the example work
\begin{document}
\begin{animateinline}[autoplay, loop]{5}
\begin{lstlisting}
listing inside animate
\end{lstlisting}
\newframe
text in frame
\newframe
\end{animateinline}

\begin{lstlisting}
listing outside animate
\end{lstlisting}

\end{document}

The error is

! LuaTeX error (ext4): destinations cannot be inside an XForm.
<argument> ... resources {\the \pdfpageresources }\@anim@box 
                                                  \xdef \@anim@lastxform {\t...

The error is really an interaction between the three packages. listing works outside the animate or without hyperref. animate works without listings or without hyperref.

Possibly related: Hyperref adds vertical space to listings which gives me the idea that listings uses some hyperref feature if the package is previously (?) loaded. Something like this is described in the Section 5.3 in the listings package manual.

alfC
  • 14,350
  • just a side note, I've read that \usepackage{hyperref} should be put at the end, after all other packages are loaded. – Nasser Jun 15 '14 at 09:47
  • @Nasser, yes but it still fails in the same way, I'll edit to remove the distraction. – alfC Jun 15 '14 at 10:00

1 Answers1

4

The problem is that package animate has to use XForm objects for the appearance streams of the annotation. There pdfTeX does not allow destinations, which are automatically added by hyperref for the listings.

A workaround is environment NoHyper of package hyperref, which disables the hyperref stuff temporarily:

\documentclass{article}
\usepackage{hyperref}
\usepackage{animate}
\usepackage{listings}
\begin{document}

\begin{NoHyper} 
\begin{animateinline}[autoplay, loop]{5}
\begin{lstlisting}
listing inside animate
\end{lstlisting}
\newframe
text in frame
\newframe
\end{animateinline}
\end{NoHyper}

\begin{lstlisting}
listing outside animate
\end{lstlisting}
\end{document}

Result

Automated solution

The environment NoHyper can be put into environment animateinline. The following example uses package etoolbox for the patching:

\documentclass{article}
\usepackage{hyperref}
\usepackage{animate}
\usepackage{listings}

\usepackage{etoolbox}
\pretocmd\animateinline{\NoHyper}{}{%
  \errmessage{Cannot patch \string\animateinline}%
}
\apptocmd\endanimateinline{\endNoHyper}{}{%
  \errmessage{Cannot patch \string\endanimateinline}%
}

\begin{document}
\begin{animateinline}[autoplay, loop]{1}
\begin{lstlisting}
listing inside animate
\end{lstlisting}
\newframe
text in frame
\newframe
\end{animateinline}

\begin{lstlisting}
listing outside animate
\end{lstlisting}
\end{document}
Heiko Oberdiek
  • 271,626
  • Works... Why is that? I don't see any links generated in normal listings. Is this something that listings does. Or is it hyperref that behaves like this for all environments (i.e. all begin...ends)? Is there an option to make hyperref skip listings or better yet skip anything inside animateinline? – alfC Jun 15 '14 at 10:05
  • 1
    @alfC: Destinations are link targets. For example, a line in a listings can be referenced and the link jumps to the referenced line. – Heiko Oberdiek Jun 15 '14 at 10:15
  • Ah, I didn't know that listings have potential link destinations at all lines. (How are they references \ref{mylisting:line20}? – alfC Jun 15 '14 at 10:19
  • 1
    @alfC: As usual: \label in the referenced line and \ref or friend for the reference. With some features like mathescape you can smuggle in the \label. – Heiko Oberdiek Jun 15 '14 at 10:23
  • Thanks for the edit, I found this limitation of animate before, so this is very useful. Maybe (@AlexG) animate should disable temporarely hyperref by default; although that could cause surprises. – alfC Jun 15 '14 at 10:24
  • @alfC: Also the whole listings can be referenced, if it uses key label. – Heiko Oberdiek Jun 15 '14 at 10:25
  • That is the confusing part, why XForm is generated even if no label has been produced. But ok, that's how things are. – alfC Jun 15 '14 at 10:25
  • @alfC: In LaTeX \label comes after the referenced counter (e.g. the famous \label after \caption, not before). The time, when the counter is assigned a new value (\refstepcounter) is usually at the beginning (of the listings, of the line in the listings, of the caption, ...); that means a good place for the destination. Thus the destination is set without knowing, whether a \label is following. – Heiko Oberdiek Jun 15 '14 at 10:40
  • 1
    @alfC: XForms have nothing to do with labels/links. XForms are at the core of animates working. XForms are self-contained graphical/textual objects which can be referenced in the page content or as appearance of PDF annotations. animate uses XForms to store the content of the animation frames. They just cannot store links and link destinations. (Very much like \includegraphics and \includepdf don't support links in the included material.) – AlexG Jun 15 '14 at 21:39
  • @AlexG, however \includegraphics behaves differently in that it fails silently (http://tex.stackexchange.com/questions/14620/how-to-preserve-hyperlinks-in-included-pdf). Which may or may not be a desired behavior of animate (currently it is not, animate fails with an error). For example animate could tell hyperref to not generate links inside the animate environment. Thanks for the clarification. – alfC Jun 16 '14 at 07:15
  • 1
    @alfC: Thanks for the suggestion. In the next version or so, nohyper will be added. – AlexG Jun 16 '14 at 15:17
  • @AlexG, yes, that will make animate work out of the box with many environments that currently fail with an error. (It will be mysterious why some hyperlink destinations don't work though.) – alfC Jun 16 '14 at 19:05
  • 1
    @alfC: For example, PDF XForm objects can be reused many times. A destination would no longer be unique. – Heiko Oberdiek Jun 16 '14 at 20:00
  • Version [20140620] of animate inserts NoHyper. Thanks for telling about NoHyper. (It is not documented in the hyperref manual.) – AlexG Jun 20 '14 at 10:41