summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2007-03-16 22:57:20 +0000
committerKarl Berry <karl@freefriends.org>2007-03-16 22:57:20 +0000
commit6b24bbb8c9fd9d68f274d903e2bcbefc0fd3e86c (patch)
tree2046aa9e69358869e72a3243a634f586a387c87c /Master/texmf-dist/tex
parent1c509078a3db7ab28a390cb21ac823ce314c650c (diff)
new latex package animate (15mar07)
git-svn-id: svn://tug.org/texlive/trunk@4040 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r--Master/texmf-dist/tex/latex/animate/animate.sty1579
1 files changed, 1579 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/animate/animate.sty b/Master/texmf-dist/tex/latex/animate/animate.sty
new file mode 100644
index 00000000000..a133d6ce5b6
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/animate/animate.sty
@@ -0,0 +1,1579 @@
+% Copyright 2007 Alexander Grahn
+
+% This material is subject to the LaTeX Project Public License. See
+% http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+% for the details of that license.
+
+% Package for creating portable, JavaScript driven animations from sets of
+% graphics files or inline graphics (e. g. latex-picture, pstricks,
+% pgf/TikZ, Asymptote, ...)
+
+% Supports LaTeX->dvips->(ps2pdf or Distiller) or pdfLaTeX workflows.
+
+% Based on the work by Jan Holocek and Petr Sojka.
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{animate}[2007/03/15]
+\RequirePackage{keyval}
+\RequirePackage{ifthen}
+\RequirePackage{ifpdf}
+\RequirePackage{calc}
+
+\DeclareOption*{}\ProcessOptions*\relax %allow anything as option
+%(package options will be processed near end of file)
+
+\ifpdf
+ \ifnum\pdftexversion<120% correct pdfTeX version?
+ \PackageError{animate}{%
+ pdf(La)TeX version >= 1.20 required
+ }{%
+ Install a more recent version!
+ }%
+ \fi%
+\else
+ %define `?pdfmark' operator; taken from the PDFmark Reference
+ \AtBeginDocument{%
+ \ifthenelse{\isundefined{\pdfmark}}{% (hyperref provides its own
+ \special{ps: % definition)
+ /pdfmark where
+ { pop globaldict /?pdfmark /exec load put }
+ {
+ globaldict
+ begin
+ /?pdfmark /pop load def
+ /pdfmark /cleartomark load def
+ end
+ }
+ ifelse
+ }%
+ }{}%
+ }
+\fi%
+
+%define our own label making commands
+\def\@anim@newkey#1#2{{\expandafter\xdef\csname#1\endcsname{#2}}}
+\def\@anim@getkeyval#1{%
+ \expandafter\ifx\csname#1\endcsname\relax%
+ undefined%
+ \else%
+ \csname#1\endcsname%
+ \fi%
+}%
+
+%missing package error message
+\def\@anim@missing#1{%
+ \PackageError{animate}{%
+ Package `#1' has not been loaded yet%
+ }{%
+ Put the line\MessageBreak%
+ `\protect\usepackage{#1}'\MessageBreak%
+ to the preamble of your document!
+ }%
+}
+
+%add AP (appearances name tree) root node to the Names dict of the PDF Catalog
+\ifpdf
+ \newcount\@anim@aproot
+ \pdfobj reserveobjnum
+ \@anim@aproot=\pdflastobj
+ \pdfnames{/AP \the\pdflastobj\space 0 R}
+ \def\@anim@buttontree{}
+ \AtEndDocument{%
+ \pdfobj useobjnum \@anim@aproot {%
+ <</Kids [\@anim@apkids\space\@anim@buttontree]>>%
+ }%
+ \pdfrefobj\pdflastobj%
+ }%
+\else
+ \special{ps:
+ mark {Catalog} <</Names <</AP <</Kids {@anim@apkids}>>>>>> /PUT pdfmark
+ }
+\fi
+
+%create name tree object from XObject hash & add a reference to it to the
+%name tree list
+\ifpdf
+ \def\@anim@apkids{}
+ \def\@anim@addtree#1{% #1 @anim@num
+ \immediate\pdfobj {<<%
+ /Names [\@anim@getkeyval{a#1.hash}]
+ /Limits [(\@anim@getkeyval{a#1.ffirst}) (\@anim@getkeyval{a#1.flast})]%
+ >>}%
+ \xdef\@anim@apkids{\@anim@apkids\the\pdflastobj\space 0 R\space}%
+ }
+\else
+ \special{ps: mark /_objdef {@anim@apkids} /type/array /OBJ pdfmark }
+ \def\@anim@addtree#1{%
+ \special{ps:
+ mark
+ /_objdef {tree@#1}
+ /type/dict
+ /OBJ pdfmark
+ mark
+ {tree@#1} <<
+ /Names [\@anim@getkeyval{a#1.hash}]
+ /Limits [(\@anim@getkeyval{a#1.ffirst}) (\@anim@getkeyval{a#1.flast})]
+ >>
+ /PUT pdfmark
+ mark {@anim@apkids} {tree@#1} /APPEND pdfmark
+ }%
+ }
+\fi
+
+\newbox\@anim@box %used for storing graphics
+\newdimen\@anim@tmpdima %length registers for occasional use
+\newdimen\@anim@tmpdimb
+
+%creates Form XObject from graphics file & appends a reference to it to the
+%XObject hash (XObject name <-> XObject reference) of the current animation;
+%also determines natural size of the graphics file
+\def\@anim@pt{pt}
+\ifpdf
+ \def\@anim@ximage#1#2#3{%#1:zero padded anim num, #2:@anim@curframe@zb,
+ \edef\@anim@curfr@zb@form{\@anim@pad{123456}{#2}}% #3:filename
+ \IfFileExists{#3}{%
+ %embed the same graphics file only once (reference doesn't exist yet)
+ \ifthenelse{\equal{\@anim@getkeyval{#3.r}}{undefined}}{%
+ \immediate\pdfximage{#3}%
+ \@anim@newkey{#3.r}{\the\pdflastximage}%
+ \@anim@newkey{#3.a}{#1}% file is part of animation #1
+ \ifnum#2=0% size (measuring the first frame only)
+ % store name of first frame XObject
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ \setbox\@anim@box=\hbox{\pdfrefximage\pdflastximage}%
+ \@anim@newkey{a#1.wd}{\the\wd\@anim@box}%
+ \@anim@newkey{a#1.ht}{\the\ht\@anim@box}%
+ \@anim@newkey{a#1.dp}{0pt}%
+ \fi%
+ }{%
+ \ifnum#2=0%
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ %retrieve previously determined size and make it the current
+ \@anim@newkey{a#1.wd}{\@anim@getkeyval{a\@anim@getkeyval{#3.a}.wd}}%
+ \@anim@newkey{a#1.ht}{\@anim@getkeyval{a\@anim@getkeyval{#3.a}.ht}}%
+ \@anim@newkey{a#1.dp}{0pt}%
+ \fi%
+ }%
+ % store name of last frame XObject
+ \@anim@newkey{a#1.flast}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{a#1.hash}{% append reference
+ \@anim@getkeyval{a#1.hash}(a#1f\@anim@curfr@zb@form)
+ \@anim@getkeyval{#3.r}\space 0 R\space%
+ }%
+ }{%
+ \PackageError{animate}{File `#3' cannot be opened for embedding.}{}%
+ }%
+ }
+\else
+ \def\@anim@bp{bp}
+ \def\@anim@ximage#1#2#3{%
+ \IfFileExists{#3}{%
+ \edef\@anim@curfr@zb@form{\@anim@pad{123456}{#2}}%
+ \ifthenelse{\equal{\@anim@getkeyval{#3.r}}{undefined}}{%
+ \Gread@eps{#3}%determine BBox (\Gin@llx, \Gin@lly, \Gin@urx, \Gin@ury)
+ \special{ps:
+ save gsave
+ mark
+ /_objdef {a#1f\@anim@curfr@zb@form}
+ /BBox [\Gin@llx\space\Gin@lly\space\Gin@urx\space\Gin@ury]
+ /BP pdfmark %begin distilling graphics into Form XObject
+ /showpage {} def /setpagedevice /pop load def
+ }%
+ \special{ps: plotfile #3}%
+ \special{ps:
+ mark /EP pdfmark %end distilling
+ grestore restore
+ }%
+ \@anim@newkey{#3.r}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{#3.a}{#1}%
+ \ifnum#2=0%
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ % determine size from file BBox, convert to pt
+ \setlength{\@anim@tmpdima}{\Gin@urx\@anim@pt}%
+ \addtolength{\@anim@tmpdima}{-\Gin@llx\@anim@pt}%
+ \setlength{\@anim@tmpdima}{\strip@pt\@anim@tmpdima\@anim@bp}%
+ \@anim@newkey{a#1.wd}{\the\@anim@tmpdima}%
+ \setlength{\@anim@tmpdima}{\Gin@ury\@anim@pt}%
+ \addtolength{\@anim@tmpdima}{-\Gin@lly\@anim@pt}%
+ \setlength{\@anim@tmpdima}{\strip@pt\@anim@tmpdima\@anim@bp}%
+ \@anim@newkey{a#1.ht}{\the\@anim@tmpdima}%
+ \@anim@newkey{a#1.dp}{0pt}%
+ \fi%
+ \message{<#3>}%
+ }{%
+ \ifnum#2=0%
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{a#1.wd}{\@anim@getkeyval{a\@anim@getkeyval{#3.a}.wd}}%
+ \@anim@newkey{a#1.ht}{\@anim@getkeyval{a\@anim@getkeyval{#3.a}.ht}}%
+ \@anim@newkey{a#1.dp}{0pt}%
+ \fi%
+ }%
+ \@anim@newkey{a#1.flast}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{a#1.hash}{%
+ \@anim@getkeyval{a#1.hash}%
+ (a#1f\@anim@curfr@zb@form)\space {\@anim@getkeyval{#3.r}}\space%
+ }%
+ }{%
+ \PackageError{animate}{File `#3' cannot be opened for embedding.}{}%
+ }%
+ }
+\fi
+
+%creates Form XObject from box contents & appends a reference to it to the
+%XObject hash (XObject name <-> XObject reference) of the current animation
+\ifpdf
+ \def\@anim@xinline#1#2#3{%#1:zero padded anim num, #2:@anim@curframe@zb,
+ \immediate\pdfxform#3% #3:box number
+ \edef\@anim@curfr@zb@form{\@anim@pad{123456}{#2}}%
+ \ifnum#2=0%
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ \fi%
+ % store name of last frame of sequence
+ \@anim@newkey{a#1.flast}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{a#1.hash}{% append reference
+ \@anim@getkeyval{a#1.hash}%
+ (a#1f\@anim@curfr@zb@form)\space\the\pdflastxform\space 0 R\space%
+ }%
+ }
+\else
+ \def\@anim@xinline#1#2#3{%
+ \def\@anim@oldunitlength{\the\unitlength}% make backup
+ \setlength{\unitlength}{1pt}%
+ %mark BBox of the graphics
+ \begin{picture}(0,0)%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.dp}}%
+ \put(0,-\strip@pt\@anim@tmpdima){%
+ \special{ps:
+ currentpoint /frame@lly exch def /frame@llx exch def
+ }%
+ }%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.wd}}%
+ \setlength{\@anim@tmpdimb}{\@anim@getkeyval{a#1.ht}}%
+ \put(\strip@pt\@anim@tmpdima,\strip@pt\@anim@tmpdimb){%
+ \special{ps:
+ currentpoint /frame@ury exch def /frame@urx exch def
+ }%
+ }%
+ \end{picture}%
+ \edef\@anim@curfr@zb@form{\@anim@pad{123456}{#2}}% cur frame num formatted
+ \setlength{\unitlength}{\@anim@oldunitlength}% restore previous unitlength
+ \special{ps:
+ save gsave
+ mark
+ /_objdef {a#1f\@anim@curfr@zb@form}
+ /BBox [frame@llx frame@lly frame@urx frame@ury]
+ /BP pdfmark
+ %flip around horizontal axis
+ { [1 0 0 -1 0 frame@lly frame@ury add ] concat } ?pdfmark
+ }%
+ \begin{picture}(0,0)%
+ \put(0,0){\box#3}%
+ \end{picture}%
+ \special{ps:
+ mark /EP pdfmark
+ grestore restore
+ }%
+ \ifnum#2=0%
+ \@anim@newkey{a#1.ffirst}{a#1f\@anim@curfr@zb@form}%
+ \fi%
+ \@anim@newkey{a#1.flast}{a#1f\@anim@curfr@zb@form}%
+ \@anim@newkey{a#1.hash}{%
+ \@anim@getkeyval{a#1.hash}%
+ (a#1f\@anim@curfr@zb@form)\space {a#1f\@anim@curfr@zb@form}\space%
+ }%
+ }
+\fi
+
+%control button faces
+\def\@anim@buttonhash{}%
+\ifpdf
+ \def\@anim@xbutton#1#2{% #1 name, #2 stroking commands
+ \immediate\pdfobj stream attr{%
+ /Type/XObject/Subtype/Form/BBox [0 0 15 15]%
+ /Resources <</ProcSet [/PDF]>>%
+ }{#2}%
+ \xdef\@anim@buttonhash{%
+ \@anim@buttonhash(btn#1)\space\the\pdflastobj\space 0 R\space%
+ }%
+ }
+ \def\@anim@btnend{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 10 w
+ 45 40 m
+ 95 75 l
+ 45 110 l
+ S
+ 0 j
+ 105 44 m
+ 105 106 l
+ S
+ }
+ \def\@anim@btnstep{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 10 w
+ 50 40 m
+ 100 75 l
+ 50 110 l
+ S
+ }
+ \def\@anim@btnplay{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 10 w
+ 50 40 m
+ 50 110 l
+ 100 75 l
+ h
+ S
+ }
+ \def\@anim@btnpause{%
+ 2.5 w
+ 1 j
+ 0 G
+ 0 10 m
+ 140 10 l
+ 140 140 l
+ 0 140 l
+ S
+ 20 w
+ 22 40 m
+ 22 110 l
+ S
+ }
+ \def\@anim@btnminus{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 15 w
+ 0 J
+ 40 75 m
+ 110 75 l
+ S
+ }
+ \def\@anim@btnplus{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 15 w
+ 0 J
+ 40 75 m
+ 110 75 l
+ 75 40 m
+ 75 110 l
+ S
+ }
+ \def\@anim@btnreset{%
+ 2.5 w
+ 1 J
+ 1 j
+ 0 G
+ 10 10 130 130 re
+ S
+ 10 w
+ 75 40 m
+ 75 110 l
+ S
+ 0 g
+ 35 50 m
+ 70 75 l
+ 35 100 l
+ f
+ 115 50 m
+ 80 75 l
+ 115 100 l
+ f
+ 2 J
+ 0 j
+ 30 75 m
+ 35 75 l
+ 120 75 m
+ 115 75 l
+ S
+ }
+ \def\@anim@makebuttons{%
+ \@anim@xbutton{EndLeft}{%
+ -0.1 0 0 0.1 15 0 cm
+ \@anim@btnend%
+ }%
+ \@anim@xbutton{EndRight}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnend%
+ }%
+ \@anim@xbutton{Minus}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnminus%
+ }%
+ \@anim@xbutton{PauseLeft}{%
+ -0.1 0 0 0.1 15 0 cm
+ \@anim@btnpause%
+ }%
+ \@anim@xbutton{PauseRight}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnpause%
+ }%
+ \@anim@xbutton{PlayLeft}{%
+ -0.1 0 0 0.1 15 0 cm
+ \@anim@btnplay%
+ }%
+ \@anim@xbutton{PlayRight}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnplay%
+ }%
+ \@anim@xbutton{Plus}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnplus%
+ }%
+ \@anim@xbutton{Reset}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnreset%
+ }%
+ \@anim@xbutton{StepLeft}{%
+ -0.1 0 0 0.1 15 0 cm
+ \@anim@btnstep%
+ }%
+ \@anim@xbutton{StepRight}{%
+ 0.1 0 0 0.1 0 0 cm
+ \@anim@btnstep%
+ }%
+ \immediate\pdfobj {<<%
+ /Names [\@anim@buttonhash]
+ /Limits [(btnEndLeft) (btnStepRight)]%
+ >>}%
+ \xdef\@anim@buttontree{\the\pdflastobj\space 0 R}%
+ \setboolean{@anim@buttonsmade}{true}%
+ }
+\else
+ \def\@anim@xbutton#1#2{% #1: name; #2: stroking commands
+ \special{ps:
+ save gsave
+ mark
+ /_objdef {btn#1}
+ /BBox [0 0 15 15]
+ /BP pdfmark { #2 } ?pdfmark mark /EP pdfmark
+ grestore restore
+ }%
+ \xdef\@anim@buttonhash{%
+ \@anim@buttonhash(btn#1)\space {btn#1}\space%
+ }%
+ }
+ \def\@anim@btnend{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1 setlinewidth
+ 4.5 4 moveto
+ 9.5 7.5 lineto
+ 4.5 11 lineto
+ stroke
+ 0 setlinejoin
+ 10.5 4.4 moveto
+ 10.5 10.6 lineto
+ stroke
+ }
+ \def\@anim@btnstep{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1 setlinewidth
+ 5 4 moveto
+ 10 7.5 lineto
+ 5 11 lineto
+ stroke
+ }
+ \def\@anim@btnplay{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1 setlinewidth
+ 5 4 moveto
+ 5 11 lineto
+ 10 7.5 lineto
+ closepath
+ stroke
+ }
+ \def\@anim@btnpause{%
+ 0 setgray
+ 0.25 setlinewidth
+ 0 setlinecap
+ 1 setlinejoin
+ 0 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 0 14 lineto
+ stroke
+ 2 setlinewidth
+ 2.2 4 moveto
+ 2.2 11 lineto
+ stroke
+ }
+ \def\@anim@btnminus{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1.5 setlinewidth
+ 0 setlinecap
+ 4 7.5 moveto
+ 11 7.5 lineto
+ stroke
+ }
+ \def\@anim@btnplus{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1.5 setlinewidth
+ 0 setlinecap
+ 4 7.5 moveto
+ 11 7.5 lineto
+ 7.5 4 moveto
+ 7.5 11 lineto
+ stroke
+ }
+ \def\@anim@btnreset{%
+ 0 setgray
+ 0.25 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ 1 1 moveto
+ 14 1 lineto
+ 14 14 lineto
+ 1 14 lineto
+ closepath
+ stroke
+ 1 setlinewidth
+ 7.5 4 moveto
+ 7.5 11 lineto
+ stroke
+ 0 setlinejoin
+ 3.5 5 moveto
+ 7 7.5 lineto
+ 3.5 10 lineto
+ closepath
+ fill
+ 11.5 5 moveto
+ 8 7.5 lineto
+ 11.5 10 lineto
+ closepath
+ fill
+ 1 setlinewidth
+ 2 setlinecap
+ 3 7.5 moveto
+ 3.5 7.5 lineto
+ 12 7.5 moveto
+ 11.5 7.5 lineto
+ stroke
+ }
+ \def\@anim@makebuttons{%
+ \@anim@xbutton{EndLeft}{%
+ [-1 0 0 1 15 0] concat
+ \@anim@btnend%
+ }%
+ \@anim@xbutton{EndRight}{%
+ \@anim@btnend%
+ }%
+ \@anim@xbutton{Minus}{%
+ \@anim@btnminus%
+ }%
+ \@anim@xbutton{PauseLeft}{%
+ [-1 0 0 1 15 0] concat
+ \@anim@btnpause%
+ }%
+ \@anim@xbutton{PauseRight}{%
+ \@anim@btnpause%
+ }%
+ \@anim@xbutton{PlayLeft}{%
+ [-1 0 0 1 15 0] concat
+ \@anim@btnplay%
+ }%
+ \@anim@xbutton{PlayRight}{%
+ \@anim@btnplay%
+ }%
+ \@anim@xbutton{Plus}{%
+ \@anim@btnplus%
+ }%
+ \@anim@xbutton{Reset}{%
+ \@anim@btnreset%
+ }%
+ \@anim@xbutton{StepLeft}{%
+ [-1 0 0 1 15 0] concat
+ \@anim@btnstep%
+ }%
+ \@anim@xbutton{StepRight}{%
+ \@anim@btnstep%
+ }%
+ \AtEndDocument{%
+ \special{ps:
+ mark /_objdef {tree@button} /type/dict /OBJ pdfmark
+ mark
+ {tree@button} <<%
+ /Names [\@anim@buttonhash]
+ /Limits [(btnEndLeft) (btnStepRight)]
+ >> /PUT
+ pdfmark
+ mark {@anim@apkids} {tree@button} /APPEND pdfmark
+ }%
+ }%
+ \setboolean{@anim@buttonsmade}{true}%
+ }
+\fi
+
+%determines file type of the sequence
+\ifpdf
+ \def\@anim@getext#1{%
+ \gdef\@anim@ext{.pdf}% we start with `pdf'
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.png}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.jpg}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.jpeg}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.jbig2}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.jb2}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \PackageError{animate}{%
+ Neither of the files\MessageBreak%
+ `#1.pdf',\MessageBreak%
+ `#1.png',\MessageBreak%
+ `#1.jpg',\MessageBreak%
+ `#1.jpeg',\MessageBreak%
+ `#1.jbig2' or\MessageBreak%
+ `#1.jb2',\MessageBreak%
+ could be found.\MessageBreak%
+ Wrong file type? Mis-spelled file name?
+ }{}%
+ }}}}}}%
+ }%
+\else
+ \def\@anim@getext#1{%
+ \gdef\@anim@ext{.eps}% we start with `eps'
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.ps}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \gdef\@anim@ext{.mps}%
+ \IfFileExists{#1\@anim@ext}{}{%
+ \PackageError{animate}{%
+ Neither of the files\MessageBreak%
+ `#1.eps',\MessageBreak%
+ `#1.ps' or\MessageBreak%
+ `#1.mps'\MessageBreak%
+ could be found.\MessageBreak%
+ Wrong file type? Mis-spelled file name?
+ }{}%
+ }}}%
+ }%
+\fi
+
+%counts embedded animations
+\newcount\@anim@num\@anim@num=0
+
+%current frame
+\newcount\@anim@curframe
+\newcount\@anim@curframe@zb% zero based
+
+%user command for embedding animation sequence
+% #1: options
+% #2: frame rate (fps)
+% #3: basename of graphics file sequence (without frame number and extension)
+% #4: first frame (zero padded integer of same width as #5)
+% #5: last frame (zero padded integer of same width as #4)
+\newcommand{\animategraphics}[5][]{%
+ \leavevmode%
+ \ifpdf\else%
+ \ifthenelse{\isundefined{\includegraphics}}{\@anim@missing{graphics}}{}%
+ \fi%
+ \@anim@reset% to default settings
+ \setkeys{anim@user}{#1}%
+ \def\@anim@base{#3}%
+ \def\@anim@first{#4}%
+ \def\@anim@last{#5}%
+ %get file name extension of the sequence
+ \@anim@getext{\@anim@base\@anim@first}%
+ %
+ %create button faces if necessary
+ \if@anim@controls%
+ \if@anim@buttonsmade\else%
+ \@anim@makebuttons%
+ \fi%
+ \fi%
+ %formatted (zero padded) animation no.
+ \edef\@anim@numform{\@anim@pad{1234}{\the\@anim@num}}%
+ \@anim@newkey{a\@anim@numform.hash}{}% empty XObject hash
+ \@anim@newkey{a\@anim@numform.fps}{#2}%
+ %
+ %read all frames of the sequence
+ \@anim@curframe=\@anim@first%
+ \@anim@curframe@zb=0%
+ \loop%
+ \ifnum\@anim@curframe>\@anim@last\else%
+ %embed graphics
+ \@anim@ximage{\@anim@numform}{\the\@anim@curframe@zb}{%
+ \@anim@base\@anim@pad{\@anim@last}{\the\@anim@curframe}\@anim@ext%
+ }%
+ \advance\@anim@curframe by 1%
+ \advance\@anim@curframe@zb by 1%
+ \@anim@newkey{a\@anim@numform.frames}{\the\@anim@curframe@zb}% total number
+ \repeat%
+ \@anim@addtree{\@anim@numform}% create name tree
+ %insert animation widget & controls
+ \vtop{%
+ \offinterlineskip%
+ \hbox{\@anim@animwidget{\@anim@numform}}%
+ \if@anim@controls%
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \setlength{\@anim@tmpdima}{0.1\@anim@tmpdima}%
+ \vskip \@anim@tmpdima%
+ \hbox to \@anim@getkeyval{a\@anim@numform.wd} {%
+ \hss%
+ \@anim@buttonwidget{\@anim@numform}{EndLeft}%
+ \@anim@buttonwidget{\@anim@numform}{StepLeft}%
+ \@anim@buttonwidget{\@anim@numform}{PlayPauseLeft}%
+ \@anim@buttonwidget{\@anim@numform}{PlayPauseRight}%
+ \@anim@buttonwidget{\@anim@numform}{StepRight}%
+ \@anim@buttonwidget{\@anim@numform}{EndRight}%
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \setlength{\@anim@tmpdima}{0.3\@anim@tmpdima}%
+ \hskip \@anim@tmpdima%
+ \@anim@buttonwidget{\@anim@numform}{Minus}%
+ \@anim@buttonwidget{\@anim@numform}{Reset}%
+ \@anim@buttonwidget{\@anim@numform}{Plus}%
+ \hss%
+ }%
+ \fi%
+ }%
+ \global\advance\@anim@num by 1%
+}%
+
+%calculates widget dimensions from natural ones, taking resizing options
+%into account
+\def\@anim@rescale#1{% #1:@anim@num
+ %original totalheight
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.ht}}%
+ \addtolength{\@anim@tmpdima}{\@anim@getkeyval{a#1.dp}}%
+ \edef\@anim@th{\the\@anim@tmpdima}%
+ %rescale height & depth
+ \ifthenelse{%
+ \NOT\equal{\@anim@boxheight}{}\AND%
+ \NOT\equal{\@anim@boxdepth}{}%
+ }{%
+ \@anim@newkey{a#1.ht}{\@anim@boxheight}%
+ \@anim@newkey{a#1.dp}{\@anim@boxdepth}%
+ }{%
+ \ifthenelse{\NOT\equal{\@anim@boxheight}{}}{%
+ \@anim@newkey{a#1.ht}{\@anim@boxheight}%
+ }{%
+ \ifthenelse{\NOT\equal{\@anim@boxdepth}{}}{%
+ \@anim@newkey{a#1.dp}{\@anim@boxdepth}%
+ }{%if neither height nor depth are given but width is, rescale
+ %ht & dp to keep aspect ratio
+ \ifthenelse{\NOT\equal{\@anim@boxwidth}{}}{%
+ \setlength{\@anim@tmpdima}{%
+ \@anim@getkeyval{a#1.ht}%
+ *\ratio{\@anim@boxwidth}{\@anim@getkeyval{a#1.wd}}%
+ }\@anim@newkey{a#1.ht}{\the\@anim@tmpdima}%
+ \setlength{\@anim@tmpdima}{%
+ \@anim@getkeyval{a#1.dp}%
+ *\ratio{\@anim@boxwidth}{\@anim@getkeyval{a#1.wd}}%
+ }\@anim@newkey{a#1.dp}{\the\@anim@tmpdima}%
+ }{}%
+ }%
+ }%
+ }%
+ \ifthenelse{\NOT\equal{\@anim@boxwidth}{}}{%rescale width
+ \@anim@newkey{a#1.wd}{\@anim@boxwidth}%
+ }{%
+ %if width is not given, but either height or depth are, scale
+ %width to keep aspect ratio
+ \ifthenelse{%
+ \NOT\equal{\@anim@boxheight}{}\OR%
+ \NOT\equal{\@anim@boxdepth}{}%
+ }{%
+ \setlength{\@anim@tmpdima}{%
+ \@anim@getkeyval{a#1.wd}%
+ *\ratio{%
+ \@anim@getkeyval{a#1.ht}+\@anim@getkeyval{a#1.dp}%
+ }{\@anim@th}%
+ }%
+ \@anim@newkey{a#1.wd}{\the\@anim@tmpdima}%
+ }{}%
+ }%
+ %apply scaling by a factor
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.wd}}%
+ \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}%
+ \@anim@newkey{a#1.wd}{\the\@anim@tmpdima}%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.ht}}%
+ \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}%
+ \@anim@newkey{a#1.ht}{\the\@anim@tmpdima}%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.dp}}%
+ \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}%
+ \@anim@newkey{a#1.dp}{\the\@anim@tmpdima}%
+}
+
+%creates animation widget
+\ifpdf
+ \def\@anim@animwidget#1{%
+ \@anim@rescale{#1}%
+ %create JavaScript objects
+ \@anim@pojscript{#1}% to be executed on PO event
+ \@anim@otherjscript{#1}% on other events in the AA dict
+ \pdfannot
+ width \@anim@getkeyval{a#1.wd}
+ height \@anim@getkeyval{a#1.ht}
+ depth \@anim@getkeyval{a#1.dp}
+ {%
+ /Subtype/Widget%
+ /FT/Btn/Ff 65536% push button
+ /T (anm@#1)%
+ /BS <</W 0>>%
+ /H/N%
+ /MK <<%
+ /TP 1% icon, no caption
+ /BG [\@anim@bg]%
+ /IF <</SW/A/S/A>>% scale icon freely within widget
+ >>%
+ /AA <<% bind JavaScripts to trigger events
+ /PO <</S/JavaScript/JS \@anim@getkeyval{a#1.pojscript}\space 0 R>>%
+ \@anim@getkeyval{a#1.otherjscript}%
+ >>%
+ }%
+ \hbox to \@anim@getkeyval{a#1.wd} {%
+ \vrule width 0pt height \@anim@getkeyval{a#1.ht}
+ depth \@anim@getkeyval{a#1.dp}%
+ \hss%
+ }%
+ }%
+\else
+ \def\@anim@animwidget#1{%
+ \@anim@rescale{#1}%
+ \def\@anim@oldunitlength{\the\unitlength}%
+ \setlength{\unitlength}{1pt}%
+ %mark annotation rectangle
+ \begin{picture}(0,0)%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.dp}}%
+ \put(0,-\strip@pt\@anim@tmpdima){%
+ \special{ps:
+ currentpoint /wid@lly exch def /wid@llx exch def
+ }%
+ }%
+ \setlength{\@anim@tmpdima}{\@anim@getkeyval{a#1.wd}}%
+ \setlength{\@anim@tmpdimb}{\@anim@getkeyval{a#1.ht}}%
+ \put(\strip@pt\@anim@tmpdima,\strip@pt\@anim@tmpdimb){%
+ \special{ps:
+ currentpoint /wid@ury exch def /wid@urx exch def
+ }%
+ }%
+ \end{picture}%
+ \setlength{\unitlength}{\@anim@oldunitlength}%
+ \@anim@pojscript{#1}%
+ \@anim@otherjscript{#1}%
+ \special{ps:
+ mark
+ /Rect [wid@llx wid@lly wid@urx wid@ury]%
+ /Subtype/Widget%
+ /FT/Btn/Ff 65536%
+ /T (anm@#1)%
+ /BS <</W 0>>%
+ /H/N%
+ /MK <<%
+ /TP 1
+ /BG [\@anim@bg]%
+ /IF <</SW/A/S/A>>%
+ >>%
+ /AA <<%
+ /PO <</S/JavaScript/JS {a#1@pojscript}>>%
+ \@anim@getkeyval{a#1.otherjscript}%
+ >>%
+ /ANN pdfmark
+ }%
+ \hbox to \@anim@getkeyval{a#1.wd} {%
+ \vrule width 0pt height \@anim@getkeyval{a#1.ht}
+ depth \@anim@getkeyval{a#1.dp}%
+ \hss%
+ }%
+ }
+\fi
+
+\newboolean{@anim@buttonsmade} %true if button faces have been made
+\setboolean{@anim@buttonsmade}{false}
+%creates control button widget
+\ifpdf
+ \def\@anim@buttonwidget#1#2{% #1: zero padded anim num, #2: action
+ \@anim@upjscript{#1}{#2}% JavaScript actions for ButtonUp events
+ %button size corresponds to current font size
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \hbox to \@anim@tmpdima {%
+ \pdfannot
+ width \@anim@tmpdima
+ height \@anim@tmpdima
+ depth 0pt
+ {%
+ /Subtype/Widget%
+ /FT/Btn/Ff 65536% push button
+ /T (btn@#1@#2)%
+ /BS <</W 0>>%
+ /H/I%
+ /MK <<%
+ /TP 1%
+ /BG [\@anim@btnbg]%
+ /IF <</SW/A/S/A>>% scale button face icon freely within widget
+ >>%
+ /A <</S/JavaScript/JS (\@anim@getkeyval{a#1.upjscript})>>%
+ }%
+ \vrule width 0pt height \@anim@tmpdima depth 0pt%
+ \hss%
+ }%
+ }%
+\else
+ \def\@anim@buttonwidget#1#2{%
+ \@anim@upjscript{#1}{#2}%
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \def\@anim@oldunitlength{\the\unitlength}%
+ \setlength{\unitlength}{1pt}%
+ \begin{picture}(0,0)%
+ \put(0,0){%
+ \special{ps:
+ currentpoint /wid@lly exch def /wid@llx exch def
+ }%
+ }%
+ \put(\strip@pt\@anim@tmpdima,\strip@pt\@anim@tmpdima){%
+ \special{ps:
+ currentpoint /wid@ury exch def /wid@urx exch def
+ }%
+ }%
+ \end{picture}%
+ \setlength{\unitlength}{\@anim@oldunitlength}%
+ \special{ps:
+ mark
+ /Rect [wid@llx wid@lly wid@urx wid@ury]
+ /Subtype/Widget
+ /FT/Btn/Ff 65536
+ /T (btn@#1@#2)
+ /BS <</W 0>>
+ /H/I
+ /MK <<
+ /TP 1
+ /BG [\@anim@btnbg]
+ /IF <</SW/A/S/A>>
+ >>%
+ /A <</S/JavaScript/JS (\@anim@getkeyval{a#1.upjscript})>>%
+ /ANN pdfmark
+ }%
+ \hbox to \the\@anim@tmpdima {%
+ \vrule width 0pt height \the\@anim@tmpdima\space depth 0pt%
+ \hss%
+ }%
+ }
+\fi
+
+\newboolean{@anim@inside} % for checking whether we are inside the
+\setboolean{@anim@inside}{false} % `animate' environment
+
+%user environment for animating inline graphics
+% #1: options
+% #2: frame rate (fps)
+\newenvironment{animate}[2][]{%
+ \leavevmode%
+ \setboolean{@anim@inside}{true}%
+ \@anim@reset% to default settings
+ \setkeys{anim@user}{#1}%
+ %create button faces if necessary
+ \if@anim@controls%
+ \if@anim@buttonsmade\else%
+ \@anim@makebuttons%
+ \fi%
+ \fi%
+ %formatted (zero padded animation number)
+ \edef\@anim@numform{\@anim@pad{1234}{\the\@anim@num}}%
+ \@anim@newkey{a\@anim@numform.hash}{}% empty XObject hash
+ \@anim@newkey{a\@anim@numform.fps}{#2}%
+ \global\@anim@curframe@zb=0%
+ \@anim@beginframe%
+ \ignorespaces%
+}{%
+ \unskip%
+ %formatted (zero padded) animation number & current zero based frame no.
+ \edef\@anim@numform{\@anim@pad{1234}{\the\@anim@num}}%
+ \@anim@endframe{\@anim@numform}{\the\@anim@curframe@zb}%
+ \global\advance\@anim@curframe@zb by 1%
+ \@anim@newkey{a\@anim@numform.frames}{\the\@anim@curframe@zb}% total number
+ \@anim@addtree{\@anim@numform}% create name tree
+ %insert animation widget & controls
+ \vtop{%
+ \offinterlineskip%
+ \hbox{\@anim@animwidget{\@anim@numform}}%
+ \if@anim@controls%
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \setlength{\@anim@tmpdima}{0.1\@anim@tmpdima}%
+ \vskip \@anim@tmpdima%
+ \hbox to \@anim@getkeyval{a\@anim@numform.wd} {%
+ \hss%
+ \@anim@buttonwidget{\@anim@numform}{EndLeft}%
+ \@anim@buttonwidget{\@anim@numform}{StepLeft}%
+ \@anim@buttonwidget{\@anim@numform}{PlayPauseLeft}%
+ \@anim@buttonwidget{\@anim@numform}{PlayPauseRight}%
+ \@anim@buttonwidget{\@anim@numform}{StepRight}%
+ \@anim@buttonwidget{\@anim@numform}{EndRight}%
+ \setlength{\@anim@tmpdima}{\@anim@btnsize}%
+ \setlength{\@anim@tmpdima}{0.3\@anim@tmpdima}%
+ \hskip \@anim@tmpdima%
+ \@anim@buttonwidget{\@anim@numform}{Minus}%
+ \@anim@buttonwidget{\@anim@numform}{Reset}%
+ \@anim@buttonwidget{\@anim@numform}{Plus}%
+ \hss%
+ }%
+ \fi%
+ }%
+ \global\advance\@anim@num by 1%
+ \setboolean{@anim@inside}{false}%
+}
+
+%usercommand for use within `animate' environment;
+%terminates the current frame and starts a new one
+\newcommand{\newframe}{%
+ \unskip%
+ \if@anim@inside\else%
+ \PackageError{animate}{%
+ \protect\newframe cannot be used\MessageBreak%
+ outside `animate' environment
+ }{}%
+ \fi%
+ \edef\@anim@numform{\@anim@pad{1234}{\the\@anim@num}}%
+ \@anim@endframe{\@anim@numform}{\the\@anim@curframe@zb}%
+ \global\advance\@anim@curframe@zb by 1%
+ \@anim@beginframe%
+ \ignorespaces%
+}%
+
+%starts a new frame
+\def\@anim@beginframe{%
+ \begin{lrbox}{\@anim@box}% store the graphics in a box
+}
+
+%terminates current frame
+\def\@anim@endframe#1#2{%
+ \end{lrbox}%
+ %determine size of graphics
+ \ifnum #2=0
+ \@anim@newkey{a#1.wd}{\the\wd\@anim@box}%
+ \@anim@newkey{a#1.ht}{\the\ht\@anim@box}%
+ \@anim@newkey{a#1.dp}{\the\dp\@anim@box}%
+ \fi%
+ %now create Form XObject of box contents
+ \@anim@xinline{#1}{#2}{\@anim@box}%
+ \message{<a\the\@anim@num, fr#2>}%
+}
+
+%prints zero padded integers
+% #1: arbitrary, non-zero integer number as template specifying the
+% width, e. g. `987654' for a width of 6 digits
+% #2: the number to be formatted (zero padded)
+\def\@anim@pad#1#2{%
+ \@anim@@pad{\@anim@template{0}{#1}}{#2}%
+}
+%low level macros used by \@anim@pad
+\def\@anim@@pad#1#2{% #1: string of zeros specifying width, #2 number
+ \ifnum1#2<1#1
+ \@anim@@pad{#1}{0#2}%
+ \else%
+ #2%
+ \fi%
+}%
+\def\@anim@template#1#2{% create template (stringed zeros) from given num
+ \ifnum10#1<1#2
+ \@anim@template{0#1}{#2}%
+ \else%
+ #1%
+ \fi%
+}%
+
+%command options
+%setting the widget size
+\define@key{anim@user}{width}{%
+ \setlength{\@anim@tmpdima}{#1}%
+ \xdef\@anim@boxwidth{\the\@anim@tmpdima}%
+}
+\define@key{anim@user}{height}{%
+ \setlength{\@anim@tmpdima}{#1}%
+ \xdef\@anim@boxheight{\the\@anim@tmpdima}%
+}
+\define@key{anim@user}{depth}{%
+ \setlength{\@anim@tmpdima}{#1}%
+ \xdef\@anim@boxdepth{\the\@anim@tmpdima}%
+}
+\define@key{anim@user}{scale}{%
+ \gdef\@anim@boxscale{#1}%
+}
+
+\define@key{anim@user}{screenbg}{%background colour
+ \gdef\@anim@bg{#1}%
+}
+\define@key{anim@user}{buttonsize}{%
+ \gdef\@anim@btnsize{#1}%
+}
+\define@key{anim@user}{buttonbg}{%background of buttons
+ \gdef\@anim@btnbg{#1}%
+}
+\newboolean{@anim@controls}
+\setboolean{@anim@controls}{false}
+\define@key{anim@user}{controls}[true]{%
+ \setboolean{@anim@controls}{#1}%
+}
+\newboolean{@anim@loop}
+\setboolean{@anim@loop}{false}
+\define@key{anim@user}{loop}[true]{%
+ \setboolean{@anim@loop}{#1}%
+}
+\newboolean{@anim@autoplay}
+\setboolean{@anim@autoplay}{false}
+\define@key{anim@user}{autoplay}[true]{%
+ \setboolean{@anim@autoplay}{#1}%
+ \if@anim@autoplay
+ \setboolean{@anim@autoresume}{false}
+ \fi%
+}
+\newboolean{@anim@autoresume}
+\setboolean{@anim@autoresume}{false}
+\define@key{anim@user}{autoresume}[true]{%
+ \setboolean{@anim@autoresume}{#1}%
+ \if@anim@autoresume\setboolean{@anim@autoplay}{false}\fi%
+}
+\newboolean{@anim@autopause}
+\setboolean{@anim@autopause}{false}
+\define@key{anim@user}{autopause}[true]{%
+ \setboolean{@anim@autopause}{#1}%
+}
+\newboolean{@anim@palindrome}
+\setboolean{@anim@palindrome}{false}
+\define@key{anim@user}{palindrome}[true]{%
+ \setboolean{@anim@palindrome}{#1}%
+}
+
+%macro to reset macros and booleans
+\def\@anim@reset{%
+ \gdef\@anim@boxscale{1.0}%
+ \gdef\@anim@boxdepth{}%
+ \gdef\@anim@boxheight{}%
+ \gdef\@anim@boxwidth{}%
+ \xdef\@anim@bg{\@anim@@bg}%
+ \xdef\@anim@btnbg{\@anim@@btnbg}%
+ \xdef\@anim@btnsize{\@anim@@btnsize}%
+ \let\if@anim@controls=\if@anim@@controls%
+ \let\if@anim@loop=\if@anim@@loop%
+ \let\if@anim@autoplay=\if@anim@@autoplay%
+ \let\if@anim@autoresume=\if@anim@@autoresume%
+ \let\if@anim@autopause=\if@anim@@autopause%
+ \let\if@anim@palindrome=\if@anim@@palindrome%
+}
+
+%package options
+\def\@anim@@bg{}%
+\define@key{anim@pkg}{screenbg}{%background colour
+ \gdef\@anim@@bg{#1}%
+}
+\def\@anim@@btnsize{1.44em}%
+\define@key{anim@pkg}{buttonsize}{%
+ \gdef\@anim@@btnsize{#1}%
+}
+\def\@anim@@btnbg{}%
+\define@key{anim@pkg}{buttonbg}{%background of buttons
+ \gdef\@anim@@btnbg{#1}%
+}
+\newboolean{@anim@@controls}
+\setboolean{@anim@@controls}{false}%
+\define@key{anim@pkg}{controls}[true]{%
+ \setboolean{@anim@@controls}{#1}%
+}
+\newboolean{@anim@@loop}
+\setboolean{@anim@@loop}{false}%
+\define@key{anim@pkg}{loop}[true]{%
+ \setboolean{@anim@@loop}{#1}%
+}
+\newboolean{@anim@@autoplay}
+\setboolean{@anim@@autoplay}{false}
+\define@key{anim@pkg}{autoplay}[true]{%
+ \setboolean{@anim@@autoplay}{#1}%
+ \if@anim@@autoplay\setboolean{@anim@@autoresume}{false}\fi%
+}
+\newboolean{@anim@@autoresume}
+\setboolean{@anim@@autoresume}{false}
+\define@key{anim@pkg}{autoresume}[true]{%
+ \setboolean{@anim@@autoresume}{#1}%
+ \if@anim@@autoresume\setboolean{@anim@@autoplay}{false}\fi%
+}
+\newboolean{@anim@@autopause}
+\setboolean{@anim@@autopause}{false}
+\define@key{anim@pkg}{autopause}[true]{%
+ \setboolean{@anim@@autopause}{#1}%
+}
+\newboolean{@anim@@palindrome}
+\setboolean{@anim@@palindrome}{false}
+\define@key{anim@pkg}{palindrome}[true]{%
+ \setboolean{@anim@@palindrome}{#1}%
+}
+
+%process package options
+\def\@anim@setpkgkeys#1{\setkeys{anim@pkg}{#1}}
+\edef\@anim@pkgopts{{\@ptionlist{animate.sty}}}
+\expandafter\@anim@setpkgkeys\@anim@pkgopts
+
+%JavaScript objects
+%animation widget's PageOpen event
+\ifpdf
+ \def\@anim@pojscript#1{%
+ \immediate\pdfobj stream {\@anim@@pojscript{#1}}%
+ \@anim@newkey{a#1.pojscript}{\the\pdflastobj}%
+ }
+\else
+ \def\@anim@pojscript#1{%
+ \special{ps:
+ mark /_objdef {a#1@pojscript} /type/stream /OBJ pdfmark
+ mark {a#1@pojscript} (\@anim@@pojscript{#1}) /PUT pdfmark
+ }%
+ }
+\fi
+\def\@anim@@pojscript#1{% #1: formatted (zero padded) animation number
+ \if@anim@controls
+ %get references to button face icons `Play' & `Pause'
+ if (typeof(icn)=="undefined") {
+ var icn = new Object();
+ icn.playLeft = this.getIcon("btnPlayLeft");
+ icn.pauseLeft = this.getIcon("btnPauseLeft");
+ icn.pauseRight = this.getIcon("btnPauseRight");
+ icn.playRight = this.getIcon("btnPlayRight");
+ }
+ \fi
+ %create animation object
+ if (typeof(a#1)=="undefined") {
+ var a#1 = new Object();
+ a#1.wid = this.getField("anm@#1"); %reference to animation widget
+ a#1.cntr = 0; %holds index of the frame to be displayed
+ if(\@anim@getkeyval{a#1.fps} == 0) {
+ a#1.dtDefault = 3.6e6;
+ }else{
+ a#1.dtDefault = Math.abs(1/\@anim@getkeyval{a#1.fps}) * 1000;
+ }
+ a#1.dt = a#1.dtDefault;
+ %get references to all animation frames
+ a#1.frame = new Array();
+ for (i=0; i<\@anim@getkeyval{a#1.frames}; i++){
+ a#1.frame[i] = this.getIcon("a#1f" + util.printf('\%06d', i));
+ }
+ %load first frame
+ a#1.wid.delay = true;
+ a#1.wid.buttonSetIcon(a#1.frame[0]);
+ a#1.wid.delay = false;
+ \if@anim@controls %references to button widgets
+ a#1.endLeft = this.getField("btn@#1@EndLeft");
+ a#1.stepLeft = this.getField("btn@#1@StepLeft");
+ a#1.playPauseLeft = this.getField("btn@#1@PlayPauseLeft");
+ a#1.playPauseRight = this.getField("btn@#1@PlayPauseRight");
+ a#1.stepRight = this.getField("btn@#1@StepRight");
+ a#1.endRight = this.getField("btn@#1@EndRight");
+ a#1.minus = this.getField("btn@#1@Minus");
+ a#1.plus = this.getField("btn@#1@Plus");
+ a#1.reset = this.getField("btn@#1@Reset");
+ %set the buttons appearances
+ a#1.endLeft.buttonSetIcon(this.getIcon("btnEndLeft"));
+ a#1.stepLeft.buttonSetIcon(this.getIcon("btnStepLeft"));
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ a#1.stepRight.buttonSetIcon(this.getIcon("btnStepRight"));
+ a#1.endRight.buttonSetIcon(this.getIcon("btnEndRight"));
+ a#1.minus.buttonSetIcon(this.getIcon("btnMinus"));
+ a#1.plus.buttonSetIcon(this.getIcon("btnPlus"));
+ a#1.reset.buttonSetIcon(this.getIcon("btnReset"));
+ \fi
+ %playing state and direction
+ a#1.isPlaying = false;
+ a#1.isPaused = false;
+ a#1.playsRight=true;
+ %actions
+ a#1.actnEndLeft = function () {
+ a#1.wid.delay = true; %suspend redraw
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.isPlaying = false;
+ a#1.isPaused = false; %because it has been explicitely stopped
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ \fi
+ a#1.cntr = 0;
+ a#1.wid.buttonSetIcon(a#1.frame[0]);
+ a#1.wid.delay = false; %redraw widget
+ };
+ \if@anim@controls
+ a#1.actnEndRight = function () {
+ a#1.wid.delay = true;
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.isPlaying = false;
+ a#1.isPaused = false;
+ a#1.cntr = \@anim@getkeyval{a#1.frames} - 1;
+ a#1.wid.buttonSetIcon(a#1.frame[a#1.cntr]);
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ a#1.wid.delay = false;
+ };
+ \fi
+ \if@anim@palindrome
+ a#1.actnNext = function () {
+ a#1.wid.delay = true;
+ if(a#1.cntr == \@anim@getkeyval{a#1.frames} - 1){
+ if(a#1.isPlaying){a#1.isPaused = true; a#1.actnPlayLeft();}
+ }else{a#1.cntr++;}
+ a#1.wid.buttonSetIcon(a#1.frame[a#1.cntr]);
+ a#1.wid.delay = false;
+ };
+ a#1.actnPrev = function () {
+ a#1.wid.delay = true;
+ if(a#1.cntr == 0){
+ if(a#1.isPlaying){a#1.isPaused = true; a#1.actnPlayRight();}
+ }else{a#1.cntr--;}
+ a#1.wid.buttonSetIcon(a#1.frame[a#1.cntr]);
+ a#1.wid.delay = false;
+ };
+ \else
+ a#1.actnNext = function () {
+ a#1.wid.delay = true;
+ if(a#1.cntr == \@anim@getkeyval{a#1.frames} - 1){
+ \if@anim@loop
+ if(a#1.isPlaying){a#1.cntr = 0;}
+ \else
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.isPlaying = false;
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ \fi
+ \fi
+ }else{a#1.cntr++;}
+ a#1.wid.buttonSetIcon(a#1.frame[a#1.cntr]);
+ a#1.wid.delay = false;
+ };
+ a#1.actnPrev = function () {
+ a#1.wid.delay = true;
+ if(a#1.cntr == 0){
+ \if@anim@loop
+ if(a#1.isPlaying){a#1.cntr = \@anim@getkeyval{a#1.frames} - 1;}
+ \else
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.isPlaying = false;
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ \fi
+ \fi
+ }else{a#1.cntr--;}
+ a#1.wid.buttonSetIcon(a#1.frame[a#1.cntr]);
+ a#1.wid.delay = false;
+ };
+ \fi
+ a#1.actnPause = function () {
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.isPlaying = false;
+ a#1.isPaused = true;
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.playLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.playRight);
+ \fi
+ };
+ a#1.actnPlayRight = function () {
+ try{app.clearInterval(a#1_int);}catch(e){}
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.pauseLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.pauseRight);
+ \fi
+ if(!a#1.isPaused){a#1.cntr = 0;}
+ a#1.playsRight = true;
+ a#1.isPlaying = true;
+ a#1.isPaused = false;
+ a#1_int = app.setInterval("a#1.actnNext()", a#1.dt);
+ };
+ a#1.actnPlayLeft = function () {
+ try{app.clearInterval(a#1_int);}catch(e){}
+ \if@anim@controls
+ a#1.playPauseLeft.buttonSetIcon(icn.pauseLeft);
+ a#1.playPauseRight.buttonSetIcon(icn.pauseRight);
+ \fi
+ if(!a#1.isPaused){a#1.cntr = \@anim@getkeyval{a#1.frames} - 1;}
+ a#1.playsRight = false;
+ a#1.isPlaying = true;
+ a#1.isPaused = false;
+ a#1_int = app.setInterval("a#1.actnPrev()", a#1.dt);
+ };
+ \if@anim@controls
+ a#1.actnIncr = function () { % speed up animation
+ try{app.clearInterval(a#1_int);}catch(e){}
+ a#1.dt /= 1.2;
+ if (a#1.isPlaying) {
+ if (a#1.playsRight) {
+ a#1_int = app.setInterval("a#1.actnNext()", a#1.dt);
+ }else{
+ a#1_int = app.setInterval("a#1.actnPrev()", a#1.dt);
+ }
+ }
+ };
+ a#1.actnDecr = function () { % slow down animation
+ a#1.dt *= 1.2;
+ try{app.clearInterval(a#1_int);}catch(e){}
+ if (a#1.isPlaying) {
+ if (a#1.playsRight) {
+ a#1_int = app.setInterval("a#1.actnNext()", a#1.dt);
+ }else{
+ a#1_int = app.setInterval("a#1.actnPrev()", a#1.dt);
+ }
+ }
+ };
+ a#1.actnReset = function () { % reset to default speed
+ a#1.dt = a#1.dtDefault;
+ try{app.clearInterval(a#1_int);}catch(e){}
+ if (a#1.isPlaying) {
+ if (a#1.playsRight) {
+ a#1_int = app.setInterval("a#1.actnNext()", a#1.dt);
+ }else{
+ a#1_int = app.setInterval("a#1.actnPrev()", a#1.dt);
+ }
+ }
+ };
+ \fi
+ }
+ \if@anim@autoplay
+ if (a#1.playsRight){
+ a#1.actnPlayRight();
+ }else{
+ a#1.actnPlayLeft();
+ }
+ \fi
+ \if@anim@autoresume
+ if(a#1.isPaused){
+ if(a#1.playsRight){a#1.actnPlayRight();}else{a#1.actnPlayLeft();}
+ }
+ \fi
+}
+%other trigger events in the anim widget's AA dictionary
+\def\@anim@otherjscript#1{%
+ \@anim@newkey{a#1.otherjscript}{%
+ /PC <</S/JavaScript/JS (% %PageClose
+ \if@anim@autopause%
+ if(a#1.isPlaying) {a#1.actnPause();}
+ \else% == autostop
+ a#1.actnEndLeft();%
+ \fi%
+ )>>%
+ /D <</S/JavaScript/JS (% pause on MouseDown
+ %disable focus rectangle
+ app.focusRect = false;%
+ if(a#1.isPlaying) {a#1.actnPause();}%
+ )>>%
+ /U <</S/JavaScript/JS (% play/resume on MouseUp
+ \if@anim@controls%
+ if (a#1.playsRight){%
+ a#1.actnPlayRight();%
+ }else{%
+ a#1.actnPlayLeft();%
+ }%
+ \else%
+ a#1.actnPlayRight();%
+ \fi%
+ )>>%
+ }%
+}
+%actions for control buttons
+\def\@anim@upjscript#1#2{%
+ \def\@anim@action{#2}%
+ \def\@anim@EndLeft{EndLeft}%
+ \def\@anim@StepLeft{StepLeft}%
+ \def\@anim@PlayPauseLeft{PlayPauseLeft}%
+ \def\@anim@PlayPauseRight{PlayPauseRight}%
+ \def\@anim@StepRight{StepRight}%
+ \def\@anim@EndRight{EndRight}%
+ \def\@anim@Minus{Minus}%
+ \def\@anim@Reset{Reset}%
+ \def\@anim@Plus{Plus}%
+ \@anim@newkey{a#1.upjscript}{%
+ app.focusRect = false;%
+ \ifx\@anim@action\@anim@EndLeft
+ a#1.actnEndLeft();%
+ \else%
+ \ifx\@anim@action\@anim@StepLeft
+ if(!a#1.isPlaying){a#1.actnPrev();}%
+ \else%
+ \ifx\@anim@action\@anim@PlayPauseLeft
+ if(a#1.isPlaying) {a#1.actnPause();}%
+ else{a#1.actnPlayLeft();}%
+ \else%
+ \ifx\@anim@action\@anim@PlayPauseRight
+ if(a#1.isPlaying) {a#1.actnPause();}%
+ else{a#1.actnPlayRight();}%
+ \else%
+ \ifx\@anim@action\@anim@StepRight
+ if(!a#1.isPlaying){a#1.actnNext();}%
+ \else%
+ \ifx\@anim@action\@anim@EndRight
+ a#1.actnEndRight();%
+ \else%
+ \ifx\@anim@action\@anim@Minus
+ a#1.actnDecr();%
+ \else%
+ \ifx\@anim@action\@anim@Reset
+ a#1.actnReset();%
+ \else%
+ \ifx\@anim@action\@anim@Plus
+ a#1.actnIncr();%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi%
+ }%
+}