% Copyright 2007--today Alexander Grahn % This material is subject to the LaTeX Project Public License. See % http://mirrors.ctan.org/macros/latex/base/lppl.txt % 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, ...) % Supports LaTeX->dvips->ps2pdf, (Xe)LaTeX->(x)dvipdfmx, LuaLaTeX and % pdfLaTeX workflows. \NeedsTeXFormat{LaTeX2e} \def\@anim@version{2018/02/28} \ProvidesPackage{animate} [\@anim@version\space PDF animations from files and inline graphics] \RequirePackage{xkeyval} \RequirePackage{ifthen} \RequirePackage{ifpdf} \RequirePackage{ifluatex} \RequirePackage{ifxetex} \RequirePackage{ifdraft} \RequirePackage{calc} \RequirePackage{graphics}%\scalebox, \resizebox, \rotatebox %driver options (the only package options we process immediately) \newboolean{@anim@dvips} \setboolean{@anim@dvips}{false} \newboolean{@anim@dvipdfmx} \setboolean{@anim@dvipdfmx}{false} \ifpdf\else \setboolean{@anim@dvips}{true}% default dvi mode \setboolean{@anim@dvipdfmx}{false} \DeclareOptionX{dvips}{% \setboolean{@anim@dvips}{true} \setboolean{@anim@dvipdfmx}{false} } \DeclareOptionX{dvipdfmx}{% \setboolean{@anim@dvipdfmx}{true} \setboolean{@anim@dvips}{false} \PassOptionsToPackage{dvipdfmx}{pdfbase} } \DeclareOptionX{xetex}{% \setboolean{@anim@dvipdfmx}{true} \setboolean{@anim@dvips}{false} \PassOptionsToPackage{xetex}{pdfbase} } \fi \newboolean{@anim@xetex} \setboolean{@anim@xetex}{false} \ifxetex \setboolean{@anim@xetex}{true} \setboolean{@anim@dvipdfmx}{true} \setboolean{@anim@dvips}{false} \fi \DeclareOptionX*{}\ProcessOptionsX*\relax %allow anything as an option %(remaining package options will be processed near end of this file) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \RequirePackage{pdfbase}%low level PDF operations \@ifpackagelater{pdfbase}{2017/09/29}{}{ \PackageError{animate}{% Support package `pdfbase.sty' too old.% }{% Please install an up to date version of `pdfbase.sty'.\MessageBreak% Aborting.% }% } \ExplSyntaxOn \let\@anim@literal\pbs_literal:nn \def\@anim@dictobj#1{ \pbs_pdfobj:nnn{}{dict}{#1} \xdef\@anim@lastobj{\pbs_pdflastobj:} } \def\@anim@arrayobj#1{ \pbs_pdfobj:nnn{}{array}{#1} \xdef\@anim@lastobj{\pbs_pdflastobj:} } \def\@anim@streamobj#1#2{ \pbs_pdfobj:nnn{}{stream}{{#1}{#2}} \xdef\@anim@lastobj{\pbs_pdflastobj:} } \def\@anim@xform#1#2#3#4#5{ \pbs_pdfxform:nnnnn{#1}{#2}{#3}{#4}{#5} \xdef\@anim@lastxform{\pbs_pdflastxform:} } \let\@anim@refxform\pbs_pdfrefxform:n \def\@anim@pdfannot#1#2#3#4{ \pbs_pdfannot:nnnn{#1}{#2}{#3}{#4} } \def\@anim@pdfwid#1#2#3#4{ \pbs_pdfannot:nnnn{#1}{#2}{#3}{#4} \pbs_appendtofields:n{\pbs_pdflastann:} } \let\@anim@pdfcatalog\pbs_pdfcatalog:n \let\@anim@fpeval\fp_eval:n \ExplSyntaxOff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \RequirePackage{ocgbase} %OCG generating and configuration macros \def\@anim@newocg#1#2{%#1:@anim@num, #2:@anim@curframe@zb \ocgbase@new@ocg{#1.#2}{}{1}% \xdef\@anim@curocg{\ocgbase@last@ocg}% } \ifpdf\else \if@anim@dvipdfmx\else % dvips %if geometry package is loaded, execute `\geometry{dvips}' right before % `\begin{document}'; not sure whether needed at all any more \let\@anim@document\document \def\document{% \endgroup% \@ifpackageloaded{geometry}{\geometry{dvips}}{}% \begingroup% \@anim@document% } \fi \fi %\pdfmdfivesum is used for hashing object references of embedded files based %on their MD5 digest (in order to avoid multiple inclusion); if it is not %available, hashing will be based on the file name \ifluatex \RequirePackage{pdftexcmds} \let\@anim@pdfmdfivesum\pdf@filemdfivesum \else \ifcsname pdfmdfivesum\endcsname \def\@anim@pdfmdfivesum#1{\pdfmdfivesum file {#1}} \else \ifcsname mdfivesum\endcsname \def\@anim@pdfmdfivesum#1{\mdfivesum file {#1}} \else \def\@anim@pdfmdfivesum#1{#1} \fi \fi \fi %creating and using global definitions \def\@anim@newkey#1#2{{\expandafter\xdef\csname#1\endcsname{#2}}} \def\@anim@getkeyval#1{\ifcsname#1\endcsname\csname#1\endcsname\fi} \def\@animate@rerunwarn{% \ifcsname @anim@rerunwarned\endcsname\else% \gdef\@anim@rerunwarned{}% \PackageWarningNoLine{animate}{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak @ Rerun to get internal references right! @\MessageBreak @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% \fi% } %macro for writing global defs to external *.aux file \def\@anim@keytoaux#1#2{% \immediate\write\@mainaux{\string\@anim@newkey{#1}{#2}}% \ifthenelse{\equal{\@anim@getkeyval{#1}}{#2}}{}{% \AtEndDocument{\@animate@rerunwarn}}% } \AtBeginDocument{% \immediate\write\@mainaux{\string\providecommand\string\@anim@newkey[2]{}}% } %missing package error message \newcommand{\@anim@missing}[2][]{% \ifthenelse{\equal{#1}{}}{% \def\@anim@pkgopt{}% }{% \def\@anim@pkgopt{[#1]}% }% \PackageError{animate}{% Package `#2' required. Put the line\MessageBreak% `\protect\usepackage\@anim@pkgopt{#2}'\MessageBreak% to the preamble of your document% }{}% } \newboolean{@anim@grxloaded} \setboolean{@anim@grxloaded}{false} \AtBeginDocument{% \@ifpackageloaded{graphicx}{\setboolean{@anim@grxloaded}{true}}{}% \gdef\@anim@lscape{}% \gdef\@anim@@lscape{:ls}% \ifdefined\landscape% \g@addto@macro{\landscape}{\gdef\@anim@lscape{:ls}}% \g@addto@macro{\endlandscape}{\gdef\@anim@lscape{}}% \fi% } % true if any of `autoplay' or `autoresume' options is set \newboolean{@anim@autoplayorresume} % true if any of `controls' or `palindrome' or `label' options is set \newboolean{@anim@timeline} %true if `timeline' option is set \newboolean{@anim@multipage} % multipage document? \newbox\@anim@box %stores animation frames \newbox\@anim@measbox % for measuring purposes \newdimen\@anim@tmpdima %length registers for occasional use \newdimen\@anim@tmpdimb \def\@anim@firstofthree#1#2#3{#1} \def\@anim@secndofthree#1#2#3{#2} \def\@anim@thirdofthree#1#2#3{#3} %macros for recalling saved nat. dimensions \def\@anim@xformnatwd#1{\expandafter\@anim@firstofthree#1} \def\@anim@xformnatht#1{\expandafter\@anim@secndofthree#1} \def\@anim@xformnatdp#1{\expandafter\@anim@thirdofthree#1} %helper macro that typesets graphics file into savebox \if@anim@dvips % dvips: no multi-page support \def\@anim@filebox#1#2{% pdftex, xetex \edef\@anim@curfile{[clip\@anim@gropts]{#1}}% \global\setbox\@anim@box=\hbox{% \expandafter\includegraphics\@anim@curfile}% } \else %pdfTeX, LuaTeX, dvipdfmx, xetex (multi-page) \def\@anim@filebox#1#2{% \edef\@anim@curfile{[clip\@anim@gropts,page=#2]{#1}}% \global\setbox\@anim@box=\hbox{% \expandafter\includegraphics\@anim@curfile}% } \fi \def\@anim@checkboxsize#1#2{% #1: box number, #2: file \ifdim\wd#1=\z@% \PackageError{animate}{% Graphics to be used for first frame% \MessageBreak must not have zero width% }{% Check content of file #2% }% \fi% \ifdim\ht#1=\z@\ifdim\dp#1=\z@% \PackageError{animate}{% Graphics to be used for first frame% \MessageBreak must not have zero height% }{% Check content of file #2% }% \fi\fi% } %create Form XObject from graphics file \def\@anim@ximage#1#2#3#4{%#1:@anim@num, #2:@anim@curframe@zb, #3:filename, %#4: page number of multipage file \edef\@anim@fingerprint{file:\@anim@pdfmdfivesum{#3}.#4.\@anim@gropts}% \edef\@anim@curxform{\@anim@getkeyval{\@anim@fingerprint}}% \ifthenelse{\equal{\@anim@curxform}{}}{% % new file.page.graphicx_options \@anim@filebox{#3}{#4}% store file in a box \@anim@xinline{#1}{#2}{\@anim@box}{!}% delegate Form XObject creation \@anim@newkey{\@anim@fingerprint}{\@anim@@lastxform}% }{% file known, re-using existing form xobject \edef\@anim@curndims{\@anim@getkeyval{natdims:\@anim@curxform}}% nat. dims \setbox\@anim@box=\hbox to \@anim@xformnatwd{\@anim@curndims}{% \vrule width \z@ height \@anim@xformnatht{\@anim@curndims} depth \@anim@xformnatdp{\@anim@curndims}\hss% }% \@anim@xinline{#1}{#2}{\@anim@box}{\@anim@curxform}% }% } %creates Form XObject from box contents \def\@anim@xinline#1#2#3#4{% \edef\@anim@curwd{\the\wd#3}% \edef\@anim@curht{\the\ht#3}% \edef\@anim@curdp{\the\dp#3}% \ifnum#2=\z@\relax% %nat. dims of zeroth frame \xdef\@anim@zframewd{\@anim@curwd}% \xdef\@anim@zframeht{\@anim@curht}% \xdef\@anim@zframedp{\@anim@curdp}% %determine size of animation widget \setbox\@anim@measbox=\hbox to \wd#3{% \vrule width \z@ height \ht#3 depth \dp#3\hss}% \@anim@scale{\@anim@measbox}% \else% \def\@anim@needresize{0}% %test if natural dimensions of the current frame differ from those %of the 0th frame \ifdim\wd#3=\@anim@zframewd\else\def\@anim@needresize{1}\fi% \ifdim\ht#3=\@anim@zframeht\else\def\@anim@needresize{1}\fi% \ifdim\dp#3=\@anim@zframedp\else\def\@anim@needresize{1}\fi% \fi% %create form xobject from box argument \ifthenelse{\equal{#4}{!}}{% %%%% new graphics %%%% %put graphics into XObject \@anim@xform{1}{0}{}{}{#3}% \xdef\@anim@@lastxform{\@anim@lastxform}% \@anim@newkey{natdims:\@anim@lastxform}{% {\@anim@curwd}{\@anim@curht}{\@anim@curdp}% }% }{% \xdef\@anim@lastxform{#4}% }% \ifnum#2>\z@\relax% %adjust size of current frame to zeroth frame's dims, if necessary \ifnum\@anim@needresize>\z@\relax% \global\setbox#3=\hbox to \@anim@curwd{% \vrule width \z@ height \@anim@curht depth \@anim@curdp% \noexpand\@anim@refxform{\@anim@lastxform}% \hss% }% \global\setbox#3=\hbox{% \raisebox{-\@anim@zframedp}{% \resizebox*{\@anim@zframewd}{% \dimexpr\@anim@zframeht+\@anim@zframedp\relax% }{\raisebox{\depth}{\box#3}}% }% }% \@anim@xform{0}{0}{}{}{#3}% \fi% \fi% %keep a record of XObject number \@anim@newkey{img@#2}{\@anim@lastxform}% \if@anim@timeline\else% \@anim@newkey{frmcontent@#2}{\@anim@getkeyval{img@#2},}% \@anim@makeframe{#1}{#2}% \fi% \message{}% } \def\@anim@insertfrmcontent#1,#2\@nil{% \ifthenelse{\equal{#1}{}}{}{% \if@anim@dvips% \@anim@refxform{{#1}}% \else% \@anim@refxform{#1}% \fi% }% \ifthenelse{\equal{#2}{}}{}{\@anim@insertfrmcontent#2\@nil}% } %inserts one animation frame into the output acc. to % \ifcase\@anim@method as % 0 & 1: non-interactive Widget annotation % 2: Form XObject referenced in the page content, tagged as OC % animation \def\@anim@makeframe#1#2{% %container box \edef\@anim@tmpvar{\@anim@getkeyval{frmcontent@#2},}% \global\setbox\@anim@box=\hbox to \@anim@zframewd{% \vrule width \z@ height \@anim@zframeht depth \@anim@zframedp% \expandafter\@anim@insertfrmcontent\@anim@tmpvar\@nil% \hss% }% %inside a `landscape' environment together with the icon and widget methods, %the frame content needs to be rotated counter-clockwise by 90 deg \ifnum\@anim@method>\@ne\else% \ifx\@anim@lscape\@anim@@lscape% \global\setbox\@anim@box=\hbox{\rotatebox{90}{\box\@anim@box}}% \fi% \fi% \ifcase\@anim@method% icon based \@anim@xform{0}{1}{}{}{\@anim@box}% %initial visibility \ifnum\@anim@poster>\@anim@mtwo\relax% insert poster frame \ifnum#2=\@anim@poster\relax% \edef\@anim@posterap{\@anim@lastxform}% \else% \ifnum\@anim@poster=\@anim@mone\relax% use last frame as poster \edef\@anim@posterap{\@anim@lastxform}% \fi% \fi% \fi% %insert (invisible) widget with current frame as appearance \@anim@pdfwid{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% /F 2% /FT/Btn/Ff 65537% /BS <>% /AP <>% /MK <>>>% /T (#1.#2)% }% \or% widget based %initial visibility \def\@anim@annotflag{/F 2}% default: hidden \ifnum\@anim@poster>\@anim@mtwo\relax% insert poster frame \ifnum#2=\@anim@poster\relax% \def\@anim@annotflag{/F 4}% not hidden + print (4) \else% \ifnum\@anim@poster=\@anim@mone\relax% use last frame as poster \ifthenelse{% \NOT\equal{\@anim@getkeyval{a#1.poster}}{}\AND% #2=\@anim@getkeyval{a#1.poster}% }{% \def\@anim@annotflag{/F 4}% }{}% \fi% \fi% \fi% %frame insertion \@anim@xform{0}{1}{}{}{\@anim@box}% \@anim@pdfwid{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% \@anim@annotflag% /FT/Btn/Ff 65537% /BS <>% /AP <>% /MK <>>>% /T (#1.#2)% }% \or% ocg based \@anim@newocg{#1}{#2}% %initial visibility \ifnum\@anim@poster=\@anim@mone\relax% use last frame as poster \ifthenelse{% \NOT\equal{\@anim@getkeyval{a#1.poster}}{}\AND% #2=\@anim@getkeyval{a#1.poster}% }{}{% \ocgbase@add@to@off@list{\@anim@curocg}% }% \else% \ifnum#2=\@anim@poster\relax\else% \ocgbase@add@to@off@list{\@anim@curocg}% \fi% \fi% \def\@anim@needresize{0}% \ifdim\@anim@animwidth=\@anim@zframewd\else% \def\@anim@needresize{1}\fi% \ifdim\@anim@animheight=\@anim@zframeht\else% \def\@anim@needresize{1}\fi% \ifdim\@anim@animdepth=\@anim@zframedp\else% \def\@anim@needresize{1}\fi% \ifnum\@anim@needresize>\z@\relax% \global\setbox\@anim@box=\hbox{% \raisebox{-\@anim@animdepth}{% \resizebox*{\@anim@animwidth}{% \dimexpr\@anim@animheight+\@anim@animdepth\relax% }{\raisebox{\depth}{\box\@anim@box}}% }% }% \fi% %frame insertion % % marked content method % \@anim@xform{0}{0}{}{}{\@anim@box}% % \ocgbase@oc@bdc{\@anim@curocg}% % \@anim@refxform{\@anim@lastxform}% % \ocgbase@oc@emc% % /OC method \@anim@xform{0}{0}{}{/OC \@anim@curocg}{\@anim@box}% \@anim@refxform{\@anim@lastxform}% \fi% } %create XObjects of all button faces \if@anim@dvips %stroking commands \def\@anim@btnend{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 6.5 1 moveto 1 1 1 6.5 2 arct 1 6.5 lineto 1 14 6.5 14 2 arct 6.5 14 lineto 14 14 14 6.5 2 arct 14 6.5 lineto 14 1 6.5 1 2 arct closepath \ifx\empty\@anim@bg\empty\else gsave \@anim@bg\space fill grestore \fi stroke % 1 setlinewidth 4.5 4.7 moveto 8.6 7.5 lineto 4.5 10.3 lineto stroke 0 setlinejoin 10.0 4.7 moveto 10.0 10.3 lineto stroke } \def\@anim@btnstep{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 6.5 1 moveto 1 1 1 6.5 2 arct 1 6.5 lineto 1 14 6.5 14 2 arct 6.5 14 lineto 14 14 14 6.5 2 arct 14 6.5 lineto 14 1 6.5 1 2 arct closepath \ifx\empty\@anim@bg\empty\else gsave \@anim@bg\space fill grestore \fi stroke % 1 setlinewidth 5.5 4.7 moveto 9.6 7.5 lineto 5.5 10.3 lineto stroke } \def\@anim@btnplay{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 0 1 moveto 14 1 14 6.5 2 arct 14 6.5 lineto 14 14 1 14 2 arct 0 14 lineto \ifx\empty\@anim@bg\empty\else gsave closepath \@anim@bg\space fill grestore \fi stroke 0.1 setlinewidth 0 14 moveto 0 1 lineto stroke % 1 setlinewidth 5 4 moveto 5 11 lineto 10 7.5 lineto closepath stroke } \def\@anim@btnpause{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 0 1 moveto 14 1 14 6.5 2 arct 14 6.5 lineto 14 14 1 14 2 arct 0 14 lineto \ifx\empty\@anim@bg\empty\else gsave closepath \@anim@bg\space fill grestore \fi stroke % 0 setlinecap 2 setlinewidth 2.2 4 moveto 2.2 11 lineto stroke } \def\@anim@btnminus{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 6.5 1 moveto 1 1 1 6.5 2 arct 1 6.5 lineto 1 14 6.5 14 2 arct 6.5 14 lineto 14 14 14 6.5 2 arct 14 6.5 lineto 14 1 6.5 1 2 arct closepath \ifx\empty\@anim@bg\empty\else gsave \@anim@bg\space fill grestore \fi stroke % 1.0 setlinewidth 0 setlinecap 4.7 7.5 moveto 10.3 7.5 lineto stroke } \def\@anim@btnplus{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 6.5 1 moveto 1 1 1 6.5 2 arct 1 6.5 lineto 1 14 6.5 14 2 arct 6.5 14 lineto 14 14 14 6.5 2 arct 14 6.5 lineto 14 1 6.5 1 2 arct closepath \ifx\empty\@anim@bg\empty\else gsave \@anim@bg\space fill grestore \fi stroke % 1.0 setlinewidth 0 setlinecap 4.7 7.5 moveto 10.3 7.5 lineto 7.5 4.7 moveto 7.5 10.3 lineto stroke } \def\@anim@btnreset{% \@anim@fg\space 0.5 setlinewidth 1 setlinecap 1 setlinejoin 6.5 1 moveto 1 1 1 6.5 2 arct 1 6.5 lineto 1 14 6.5 14 2 arct 6.5 14 lineto 14 14 14 6.5 2 arct 14 6.5 lineto 14 1 6.5 1 2 arct closepath \ifx\empty\@anim@bg\empty\else gsave \@anim@bg\space fill grestore \fi stroke % 1 setlinewidth 7.5 4.7 moveto 7.5 10.3 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#1{% #1: @anim@num \@anim@xbutton{EndLeft}{% [-1 0 0 1 15 0] concat \ifx\@anim@lscape\@anim@@lscape [0 -1 -1 0 15 15] concat \fi% \@anim@btnend}{#1}% \@anim@xbutton{EndRight}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnend}{#1}% \@anim@xbutton{Minus}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnminus}{#1}% \@anim@xbutton{PauseLeft}{% [-1 0 0 1 15 0] concat \ifx\@anim@lscape\@anim@@lscape [0 -1 -1 0 15 15] concat \fi% \@anim@btnpause}{#1}% \@anim@xbutton{PauseRight}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnpause}{#1}% \@anim@xbutton{PlayLeft}{% [-1 0 0 1 15 0] concat \ifx\@anim@lscape\@anim@@lscape [0 -1 -1 0 15 15] concat \fi% \@anim@btnplay}{#1}% \@anim@xbutton{PlayRight}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnplay}{#1}% \@anim@xbutton{Plus}{\@anim@btnplus}{#1}% \@anim@xbutton{Reset}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnreset}{#1}% \@anim@xbutton{StepLeft}{% [-1 0 0 1 15 0] concat \ifx\@anim@lscape\@anim@@lscape [0 -1 -1 0 15 15] concat \fi% \@anim@btnstep}{#1}% \@anim@xbutton{StepRight}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnstep}{#1}% } \def\@anim@xbutton#1#2#3{% #1: name; #2: stroking commands, #3 @anim@num \global\setbox\@anim@box=\hbox to 15bp {\vbox to 15bp {\vss% \@anim@literal{}{#2}% }\hss}% %distill box into XObject \@anim@xform{0}{1}{}{% \ifx\empty\@anim@alpha\empty\else/Group <>\fi% }{\@anim@box}% %nested XObject if transparency is to be added \ifx\empty\@anim@alpha\empty\else% \global\setbox\@anim@box=\hbox to 15bp {\vbox to 15bp {\vss% \@anim@literal{direct}{% /.setopacityalpha where {% %Ghostscript pop \@anim@alpha\space .setopacityalpha% }{% %Distiller mark /CA \@anim@alpha /ca \@anim@alpha /SetTransparency pdfmark% } ifelse% }% \@anim@refxform{\@anim@lastxform}% }\hss}% \@anim@xform{0}{0}{}{}{\@anim@box}% \fi% \@anim@newkey{btn#1:#3}{\@anim@lastxform}% } \else %pdftex/dvipdfmx/xetex %stroking commands \def\@anim@btnend{% 5 w 1 J 1 j \@anim@fg\space 65 10 m 30 10 l 18.957 10 10 18.957 10 30 c 10 120 l 10 131.043 18.957 140 30 140 c 120 140 l 131.043 140 140 131.043 140 120 c 140 30 l 140 18.957 131.043 10 120 10 c \ifx\empty\@anim@bg\empty s \else\@anim@bg\space b \fi % 10 w 45 47 m 86 75 l 45 103 l S 0 j 100 47 m 100 103 l S } \def\@anim@btnstep{% 5 w 1 J 1 j \@anim@fg\space 65 10 m 30 10 l 18.957 10 10 18.957 10 30 c 10 120 l 10 131.043 18.957 140 30 140 c 120 140 l 131.043 140 140 131.043 140 120 c 140 30 l 140 18.957 131.043 10 120 10 c \ifx\empty\@anim@bg\empty s \else\@anim@bg\space b \fi % 10 w 55 47 m 96 75 l 55 103 l S } \def\@anim@btnplay{% 5 w 1 J 1 j \@anim@fg\space 0 10 m 120 10 l 131.043 10 140 18.957 140 30 c 140 120 l 140 131.043 131.043 140 120 140 c 0 140 l \ifx\empty\@anim@bg\empty S \else\@anim@bg\space B \fi 1 w 0 140 m 0 10 l S % 10 w 50 40 m 50 110 l 100 75 l s } \def\@anim@btnpause{% 5 w 1 J 1 j \@anim@fg\space 0 10 m 120 10 l 131.043 10 140 18.957 140 30 c 140 120 l 140 131.043 131.043 140 120 140 c 0 140 l \ifx\empty\@anim@bg\empty S \else\@anim@bg\space B \fi % 0 J 20 w 22 40 m 22 110 l S } \def\@anim@btnminus{% 5 w 1 J 1 j \@anim@fg\space 65 10 m 30 10 l 18.957 10 10 18.957 10 30 c 10 120 l 10 131.043 18.957 140 30 140 c 120 140 l 131.043 140 140 131.043 140 120 c 140 30 l 140 18.957 131.043 10 120 10 c \ifx\empty\@anim@bg\empty s \else\@anim@bg\space b \fi % 10 w 0 J 47 75 m 103 75 l S } \def\@anim@btnplus{% 5 w 1 J 1 j \@anim@fg\space 65 10 m 30 10 l 18.957 10 10 18.957 10 30 c 10 120 l 10 131.043 18.957 140 30 140 c 120 140 l 131.043 140 140 131.043 140 120 c 140 30 l 140 18.957 131.043 10 120 10 c \ifx\empty\@anim@bg\empty s \else\@anim@bg\space b \fi % 10 w 0 J 47 75 m 103 75 l 75 47 m 75 103 l S } \def\@anim@btnreset{% 5 w 1 J 1 j \@anim@fg\space 65 10 m 30 10 l 18.957 10 10 18.957 10 30 c 10 120 l 10 131.043 18.957 140 30 140 c 120 140 l 131.043 140 140 131.043 140 120 c 140 30 l 140 18.957 131.043 10 120 10 c \ifx\empty\@anim@bg\empty s \else\@anim@bg\space b \fi % 10 w 75 47 m 75 103 l S \@anim@@@fg\space 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#1{% \@anim@xbutton{EndLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnend\space Q% }{#1}% \@anim@xbutton{EndRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnend\space Q% }{#1}% \@anim@xbutton{Minus}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnminus\space Q% }{#1}% \@anim@xbutton{PauseLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnpause\space Q% }{#1}% \@anim@xbutton{PauseRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnpause\space Q% }{#1}% \@anim@xbutton{PlayLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnplay\space Q% }{#1}% \@anim@xbutton{PlayRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnplay\space Q% }{#1}% \@anim@xbutton{Plus}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnplus\space Q% }{#1}% \@anim@xbutton{Reset}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnreset\space Q% }{#1}% \@anim@xbutton{StepLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnstep\space Q% }{#1}% \@anim@xbutton{StepRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnstep\space Q% }{#1}% } %XObject creation \def\@anim@xbutton#1#2#3{% #1 name, #2 stroking commands, #3 @anim@num \@anim@streamobj{% /Type/XObject/Subtype/Form/BBox [0 0 15 15] \ifx\empty\@anim@alpha\empty\else% /Group <>% \fi% }{#2}% \ifx\empty\@anim@alpha\empty\else% \@anim@streamobj{% /Type/XObject/Subtype/Form/BBox [0 0 15 15]% /Resources <<% /ExtGState <<% /R1 <<% /Type/ExtGState/ca \@anim@alpha/CA \@anim@alpha/AIS false% >>% >>% /XObject <>% >>% }{/R1 gs /R2 Do}% \fi% \@anim@newkey{btn#1:#3}{\@anim@lastobj}% } \fi %determines file type of the sequence \def\zap@finalspace#1 \@nil{#1} \ifpdf \def\@anim@getpath#1#2{% #2: empty | user provided file extension \ifx\@empty#2\@empty% \gdef\@anim@ext{.pdf}% we start with `pdf' \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.mps}% \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}{}{% \gdef\@anim@ext{.jp2}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.j2k}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.jpx}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% None of the files\MessageBreak% `#1.pdf',\MessageBreak% `#1.mps',\MessageBreak% `#1.png',\MessageBreak% `#1.jpg',\MessageBreak% `#1.jpeg',\MessageBreak% `#1.jbig2',\MessageBreak% `#1.jb2',\MessageBreak% `#1.jp2',\MessageBreak% `#1.j2k' or\MessageBreak% `#1.jpx',\MessageBreak% could be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }}}}}}}}}}% \else% \gdef\@anim@ext{.#2}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% File `#1.#2' could not be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }% \fi% \xdef\@anim@pathtofile{\expandafter\zap@finalspace\@filef@und\@nil}% }% \else \if@anim@dvipdfmx %XeLaTeX, dvipdfmx \def\@anim@getpath#1#2{% \ifx\@empty#2\@empty% \gdef\@anim@ext{.pdf}% we start with `pdf' \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.mps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.eps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.ps}% \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{.bmp}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% None of the files\MessageBreak% `#1.pdf',\MessageBreak% `#1.mps',\MessageBreak% `#1.eps',\MessageBreak% `#1.ps',\MessageBreak% `#1.png',\MessageBreak% `#1.jpg',\MessageBreak% `#1.jpeg' or\MessageBreak% `#1.bmp'\MessageBreak% could be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }}}}}}}}% \else% \gdef\@anim@ext{.#2}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% File `#1.#2' could not be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }% \fi% \xdef\@anim@pathtofile{\expandafter\zap@finalspace\@filef@und\@nil}% }% \else %dvips \def\@anim@getpath#1#2{% \ifx\@empty#2\@empty% \gdef\@anim@ext{.eps}% we start with `eps' \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.mps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.ps}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% None of the files\MessageBreak% `#1.eps',\MessageBreak% `#1.mps' or\MessageBreak% `#1.ps'\MessageBreak% could be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }}}% \else% \gdef\@anim@ext{.#2}% \IfFileExists{#1\@anim@ext}{}{% \PackageError{animate}{% File `#1.#2' could not be found.\MessageBreak% Wrong file type? Mis-spelled file name?% }{}% }% \fi% \xdef\@anim@pathtofile{\expandafter\zap@finalspace\@filef@und\@nil}% }% \fi \fi %counts embedded animations \newcount\@anim@num\@anim@num=\z@% %current frame \newcount\@anim@curframe \newcount\@anim@curframe@zb %zero based %draftbox \def\@anim@draftbox{% \begingroup% \vtop{% draw boxes \offinterlineskip% \hbox{\raisebox{-\@anim@animdepth}{% \frame{% \rule{0pt}{\@anim@animtotalheight}\hskip\@anim@animwidth% }% }}% \if@anim@controls% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \setlength{\@anim@tmpdimb}{\z@}% \vskip 0.1\@anim@tmpdima% \hbox to \@anim@animwidth {% \hss% \setboolean{@anim@controls@firstgrp}{false}% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@play% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@firstgrp% \frame{\phantom{\rule{\@anim@tmpdimb}{\@anim@tmpdima}}}% \fi% \if@anim@controls@speed% \if@anim@controls@firstgrp\hskip 0.3\@anim@tmpdima\fi% \frame{\phantom{\rule{3\@anim@tmpdima}{\@anim@tmpdima}}}% \fi% \hss% }% \fi% }% \endgroup% } \ifpdf %detects multipage PDF and corrects user supplied page range \def\@anim@checkmultipage#1#2{% #1: file base name, #2 user provided file ext \ifx\@empty#2\@empty% \IfFileExists{#1.pdf}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.pdf}% }{% \IfFileExists{#1.jbig2}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.jbig2}% }{% \IfFileExists{#1.jb2}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.jb2}% }{}% }% }% \else% \IfFileExists{#1.#2}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.#2}% }{}% \fi% \if@anim@multipage% \xdef\@anim@pathtofile{\expandafter\zap@finalspace\@filef@und\@nil}% \pdfximage page 1 {\@anim@pathtofile}% \@anim@curframe=\pdflastximagepages% \advance\@anim@curframe by -\@ne%since \pdfximagepages is 1-based \edef\@anim@lastpage{\the\@anim@curframe}% \ifx\@anim@first\@empty% \gdef\@anim@first{0}% \else% \ifnum\@anim@first<\z@\relax\gdef\@anim@first{0}\fi% \ifnum\@anim@first>\@anim@lastpage\relax% \xdef\@anim@first{\@anim@lastpage}% \fi% \fi% \ifx\@anim@last\@empty% \xdef\@anim@last{\@anim@lastpage}% \else% \ifnum\@anim@last<\z@\relax\gdef\@anim@last{0}\fi% \ifnum\@anim@last>\@anim@lastpage\relax% \xdef\@anim@last{\@anim@lastpage}% \fi% \fi% \@anim@curframe=\@anim@first% \advance\@anim@curframe by \@ne% \xdef\@anim@first{\the\@anim@curframe}% \@anim@curframe=\@anim@last% \advance\@anim@curframe by \@ne% \xdef\@anim@last{\the\@anim@curframe}% \fi% }% \else \if@anim@xetex \def\@anim@checkmultipage#1#2{% \ifx\@empty#2\@empty% \IfFileExists{#1.pdf}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.pdf}% }{}% \else% \IfFileExists{#1.#2}{% \setboolean{@anim@multipage}{true}% \gdef\@anim@ext{.#2}% }{}% \fi% \if@anim@multipage% \xdef\@anim@pathtofile{\expandafter\zap@finalspace\@filef@und\@nil}% \@anim@curframe=\XeTeXpdfpagecount "\@anim@pathtofile"% \advance\@anim@curframe by -\@ne%since XeTeXpdfpagecount is 1-based \edef\@anim@lastpage{\the\@anim@curframe}% \ifx\@anim@first\@empty% \gdef\@anim@first{0}% \else% \ifnum\@anim@first<\z@\relax\gdef\@anim@first{0}\fi% \ifnum\@anim@first>\@anim@lastpage\relax% \xdef\@anim@first{\@anim@lastpage}% \fi% \fi% \ifx\@anim@last\@empty% \xdef\@anim@last{\@anim@lastpage}% \else% \ifnum\@anim@last<\z@\relax\gdef\@anim@last{0}\fi% \ifnum\@anim@last>\@anim@lastpage\relax% \xdef\@anim@last{\@anim@lastpage}% \fi% \fi% \@anim@curframe=\@anim@first% \advance\@anim@curframe by \@ne% \xdef\@anim@first{\the\@anim@curframe}% \@anim@curframe=\@anim@last% \advance\@anim@curframe by \@ne% \xdef\@anim@last{\the\@anim@curframe}% \fi% }% \else %no multi-page support in dvips %although dvipdfmx actually has multi-page support, it lacks a way to %determine the total page count which is needed here \def\@anim@checkmultipage#1{\setboolean{@anim@multipage}{false}}% \fi \fi %environment for setting LTR typesetting direction \def\@anim@beginLTR{% \ifdefined\textdir% LuaTeX \begingroup% \edef\@anim@curTxtDir{\the\textdir}% \textdir TLT\relax% \else% e-TeX based engines \ifnum\TeXXeTstate>\z@\beginL\fi% \fi% } \def\@anim@endLTR{% \ifdefined\textdir% \endgroup% \else% \ifnum\TeXXeTstate>\z@\endL\fi% \fi% } %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 (integer) % #5: last frame (integer) \newcommand{\animategraphics}[5][]{% \@anim@endsanitize% \leavevmode% \if@anim@grxloaded\else% \if@anim@dvipdfmx\if@anim@xetex% \@anim@missing{graphicx}\else% \@anim@missing[dvipdfmx]{graphicx}\fi% \else% \@anim@missing{graphicx}% \fi% \fi% \@anim@reset% to default settings \begingroup% \@anim@beginLTR% \ifcsname Ginput@path\endcsname% make use of graphic[xs] search path \let\input@path\Ginput@path% \fi% \setkeys{anim@user}{#1}% \ifthenelse{\boolean{@anim@autoplay}\OR\boolean{@anim@autoresume}}{% \setboolean{@anim@autoplayorresume}{true}% }{}% \ifthenelse{\NOT\boolean{@anim@controls}\AND\boolean{@anim@step}}{% \setboolean{@anim@loop}{true}% }{}% \if@anim@step% %for stepping animations, ignore any `controls' settings except \setboolean{@anim@controls@play}{false}% `step' and `stop' \setboolean{@anim@controls@speed}{false}% \setboolean{@anim@controls}{false}% \if@anim@controls@stop\setboolean{@anim@controls}{true}\fi% \if@anim@controls@step\setboolean{@anim@controls}{true}\fi% \fi% \def\@anim@base{#3}% \def\@anim@first{#4}% \def\@anim@last{#5}% \@anim@checkmultipage{\@anim@base}{\@anim@ftype}%test for multipage file \if@anim@multipage\else% cope with wrong user input \ifthenelse{\equal{#4}{}\OR\equal{#5}{}}{% \PackageError{animate}{% Missing frame number in \protect\animategraphics\space command% }{}% }{}% \ifthenelse{\@anim@first<\z@\OR\@anim@last<\z@}{% \PackageError{animate}{% Negative frame numbers not allowed% }{}% }{}% \fi% \def\@anim@relop{>}% \edef\@anim@numtemplate{\@anim@first}% \ifnum\@anim@first>\@anim@last\relax% \edef\@anim@every{-\@anim@every}% \def\@anim@relop{<}% \edef\@anim@numtemplate{\@anim@last}% \fi% \global\@anim@curframe=\@anim@first% \global\@anim@curframe@zb=\z@% % \if@anim@draft% \if@anim@multipage% %store file in a box \@anim@filebox{\@anim@pathtofile}{\@anim@first}% \else% %get file name extension \@anim@getpath{\@anim@base\@anim@first}{\@anim@ftype}% \@anim@filebox{\@anim@pathtofile}{1}% \fi% \@anim@scale{\@anim@box}% %draw draftbox according to dimensions of the first frame \@anim@draftbox% \else% \if@anim@controls% %create button faces only once in the current colour combination \ifcsname btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape\endcsname\else% \@anim@makebuttons{\the\@anim@num}% \@anim@newkey{% btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape}{\the\@anim@num}% \fi% \fi% \xdef\@anim@nfps{#2\space}% current frame rate \xdef\@anim@nfps{\expandafter\zap@space\@anim@nfps\@empty}% \ifdim\@anim@nfps\p@<\z@% \PackageError{animate}{% Negative frame rate `\@anim@nfps' is not allowed% }{}% \fi% \xdef\@anim@fps{\@anim@nfps}% % %read all frames of the sequence \loop\ifnum\@anim@curframe\@anim@relop\@anim@last\relax\else% \if@anim@multipage% %embed graphics \@anim@ximage{\the\@anim@num}{\the\@anim@curframe@zb}{% \@anim@pathtofile}{\the\@anim@curframe}% \else% %get path to current file end its extension \@anim@getpath{% \@anim@base\@anim@pad{\@anim@numtemplate}{\the\@anim@curframe}% }{\@anim@ftype}% %embed graphics \@anim@ximage{\the\@anim@num}{\the\@anim@curframe@zb}{% \@anim@pathtofile}{1}% \fi% \global\advance\@anim@curframe by \@anim@every% \global\advance\@anim@curframe@zb by \@ne% \repeat% \xdef\@anim@frames{\the\@anim@curframe@zb}% total number \global\@anim@tmpcnt=\@anim@frames% \global\advance\@anim@tmpcnt by -\@ne% \xdef\@anim@maxframe{\the\@anim@tmpcnt}% highest frame index %build timeline from optional timeline file \@anim@sanitizeJS% \if@anim@timeline\@anim@buildtmln{\the\@anim@num}\fi% % if last frame used as poster, write frame num to aux file \ifnum\@anim@poster=\@anim@mone\relax% \@anim@keytoaux{a\the\@anim@num.poster}{\@anim@maxframe}% \fi% %insert animation widget & controls \@anim@insertwidgets{\the\@anim@num}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape}}% \@anim@endsanitize% \fi% \@anim@endLTR% \endgroup% \global\advance\@anim@num by \@ne% }% %adjust catcode of `:' character within \animategraphics \let\@anim@animategraphics\animategraphics \def\animategraphics{\@anim@sanitizeColon\@anim@animategraphics} %inserts animation and control button widgets \newboolean{@anim@controls@firstgrp} \def\@anim@insertwidgets#1#2{%#1:@anim@num, #2 existing btn colour combination \vtop{% \offinterlineskip% \hbox{\@anim@animwidget{#1}}% \if@anim@controls% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \vskip 0.1\@anim@tmpdima% \hbox to \@anim@animwidth {% \hss% \def\@anim@tooltip{}% \setboolean{@anim@controls@firstgrp}{false}% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \@anim@buttonwidget{#1}{EndLeft}{EndLeft:#2}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \@anim@buttonwidget{#1}{StepLeft}{StepLeft:#2}% \fi% \if@anim@controls@play% \setboolean{@anim@controls@firstgrp}{true}% \@anim@buttonwidget{#1}{PauseLeft}{PauseLeft:#2}% \@anim@buttonwidget{#1}{PlayLeft}{PlayLeft:#2}% \@anim@buttonwidget{#1}{PlayPauseLeft}{}% \@anim@buttonwidget{#1}{PauseRight}{PauseRight:#2}% \@anim@buttonwidget{#1}{PlayRight}{PlayRight:#2}% \@anim@buttonwidget{#1}{PlayPauseRight}{}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \@anim@buttonwidget{#1}{StepRight}{StepRight:#2}% \fi% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \@anim@buttonwidget{#1}{EndRight}{EndRight:#2}% \fi% \if@anim@controls@speed% \if@anim@controls@firstgrp\hskip 0.3\@anim@tmpdima\fi% \def\@anim@tooltip{/TU (slower)}% \@anim@buttonwidget{#1}{Minus}{Minus:#2}% \def\@anim@tooltip{/TU (default speed)}% \@anim@buttonwidget{#1}{Reset}{Reset:#2}% \def\@anim@tooltip{/TU (faster)}% \@anim@buttonwidget{#1}{Plus}{Plus:#2}% \fi% \hss% }% \fi% }% } \newcount\@anim@resizeflags% resizing flags according to options given. % %set animation widget dimensions \def\@anim@scale#1{% #1: box number \begingroup% %natural dimensions \width, \height, \depth, \totalheight \def\width{\wd#1}% \def\height{\ht#1}% \def\depth{\dp#1}% \let\totalheight\@anim@tmpdimb% \setlength{\totalheight}{\dimexpr\height+\depth\relax}% %evaluate resizing options \xdef\@anim@animwidth{\the\dimexpr\@anim@widtharg\relax}% \xdef\@anim@animheight{\the\dimexpr\@anim@heightarg\relax}% \xdef\@anim@animtotalheight{\the\dimexpr\@anim@totheightarg\relax}% \endgroup% %correct wrong option combination; totalheight overrides height \ifnum\@anim@resizeflags=3\relax% height+totalheight->totalheight \global\@anim@resizeflags=\@ne% \fi% \ifnum\@anim@resizeflags=7\relax% height+totalheight+width->totalheight+width \global\@anim@resizeflags=5% \fi% %now resize \ifcase\@anim@resizeflags% bit 2^2=width, 2^1=height, 2^0=totalhight given \or% 1 \global\setbox#1=\hbox{\resizebox*{!}{\@anim@animtotalheight}{\box#1}}% \or% 2 \global\setbox#1=\hbox{\resizebox{!}{\@anim@animheight}{\box#1}}% \or\or% 4 \global\setbox#1=\hbox{\resizebox{\@anim@animwidth}{!}{\box#1}}% \or% 5 \if@anim@iso% \setlength{\@anim@tmpdima}{% \totalheightof{\usebox#1}*\ratio{\@anim@animwidth}{\wd#1}}% \ifdim\@anim@tmpdima<\z@\@anim@tmpdima=-\@anim@tmpdima\fi% \setlength{\@anim@tmpdimb}{\@anim@animtotalheight}% \ifdim\@anim@tmpdimb<\z@\@anim@tmpdimb=-\@anim@tmpdimb\fi% \ifdim\@anim@tmpdima<\@anim@tmpdimb% \global\setbox#1=\hbox{\resizebox*{\@anim@animwidth}{!}{\box#1}}% \else% \global\setbox#1=\hbox{% \resizebox*{!}{\@anim@animtotalheight}{\box#1}}% \fi% \else% \global\setbox#1=\hbox{% \resizebox*{\@anim@animwidth}{\@anim@totheightarg}{\box#1}}% \fi% \or% 6 \if@anim@iso% \setlength{\@anim@tmpdima}{\ht#1*\ratio{\@anim@animwidth}{\wd#1}}% \ifdim\@anim@tmpdima<\z@\@anim@tmpdima=-\@anim@tmpdima\fi% \setlength{\@anim@tmpdimb}{\@anim@animheight}% \ifdim\@anim@tmpdimb<\z@\@anim@tmpdimb=-\@anim@tmpdimb\fi% \ifdim\@anim@tmpdima<\@anim@tmpdimb% \global\setbox#1=\hbox{\resizebox{\@anim@animwidth}{!}{\box#1}}% \else% \global\setbox#1=\hbox{\resizebox{!}{\@anim@animheight}{\box#1}}% \fi% \else% \global\setbox#1=\hbox{% \resizebox{\@anim@animwidth}{\@anim@animheight}{\box#1}}% \fi% \fi% %apply scale \ifdim\@anim@boxscale\p@=\@ne\p@\else% \global\setbox#1=\hbox{\scalebox{\@anim@boxscale}{\box#1}}% \fi% %dimensions after resizing \xdef\@anim@animwidth{\the\wd#1}% \xdef\@anim@animheight{\the\ht#1}% \xdef\@anim@animdepth{\the\dp#1}% \xdef\@anim@animtotalheight{\the\dimexpr\ht#1+\dp#1\relax}% } %interactive Widget annotation serving as animation frame container / that is %overlayed on the non-interactive frame Widgets or on the page content with %frame OCGs \def\@anim@animwidget#1{% \@anim@pojscript{#1}% \@anim@pcjscript{#1}% \@anim@otherjscript{#1}% \def\@anim@annotflag{}% \ifnum\@anim@poster>\@anim@maxframe\relax% \PackageError{animate}{% Poster frame `\@anim@poster' is out-of-bounds\MessageBreak% on input line \the\inputlineno.\MessageBreak% Try option `poster=last'% }{}% \fi% \ifnum\@anim@method=\z@\relax% \def\@anim@annotflag{/F 4}% 4=allow printing \ifnum\@anim@poster=\@anim@mtwo\relax% \ifdefined\@anim@apdummy\else% empty appearance widget \setbox\@anim@box=\hbox{\phantom{x}}% \@anim@xform{0}{0}{}{}{\@anim@box}% \xdef\@anim@apdummy{\@anim@lastxform}% \@anim@pdfwid{1ex}{1ex}{\z@}{% /Subtype/Widget% /F 2% /FT/Btn/Ff 65537% /BS <>% /AP <>% /MK <>>>% /T (0000)% }% \fi% \def\@anim@apmk{\@anim@apdummy}% \else% \def\@anim@apmk{\@anim@posterap}% \fi% \else% \ifdefined\@anim@apdummy\else% empty appearance dummy \setbox\@anim@box=\hbox{\phantom{x}}% \@anim@xform{0}{0}{}{}{\@anim@box}% \xdef\@anim@apdummy{\@anim@lastxform}% \fi% \def\@anim@apmk{\@anim@apdummy}% \fi% %this is for Foxit compatibility: % Widget annots don't seem to acknowledge /P* events % a non-interactive /Screen annotation for initializing the animation % upon PageOpen/PageVisible events and for clean-up upon PageClose/ % PageInvisible events \@anim@pdfannot{1ex}{1ex}{\z@}{% /Subtype/Screen/F 2% /AA <<% /PV <>% PageVisible /PO <>% PageOpen /PI <>% PageInvisible /PC <>% PageClose >>% }% \@anim@pdfwid{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% /FT/Btn/Ff \@anim@btnflag% \@anim@annotflag% /BS <>% /H/N% /T (anm#1)% /Contents (animation by animate[\@anim@version])% /AA <<% /PV <>% PageVisible /PO <>% PageOpen /PI <>% PageInvisible /PC <>% PageClose \@anim@otherjscriptkey% >>% /AP <>% /MK <>>>% }% \hbox to \@anim@animwidth {% \vrule width 0pt height \@anim@animheight depth \@anim@animdepth% \hss% }% } %creates control button widget \newboolean{@anim@js} \newboolean{@anim@mk} \def\@anim@buttonwidget#1#2#3{%#1:@anim@num, #2:action, #3:button face XObject \def\@anim@annotflag{/F 0}% visible, but don't print \def\@anim@buttonname{#2}\@anim@jstrue\@anim@mktrue% \def\@anim@arg{PlayLeft}% \ifx\@anim@arg\@anim@buttonname\@anim@jsfalse\fi% _ \def\@anim@arg{PauseLeft}% %hidden, don't print | \ifx\@anim@arg\@anim@buttonname\@anim@jsfalse\def\@anim@annotflag{/F 2}\fi%_| \def\@anim@arg{PlayRight}% \ifx\@anim@arg\@anim@buttonname\@anim@jsfalse\fi% \def\@anim@arg{PauseRight}% \ifx\@anim@arg\@anim@buttonname\@anim@jsfalse\def\@anim@annotflag{/F 2}\fi% \def\@anim@arg{PlayPauseLeft}% \ifx\@anim@arg\@anim@buttonname\@anim@mkfalse\fi% \def\@anim@arg{PlayPauseRight}% \ifx\@anim@arg\@anim@buttonname\@anim@mkfalse\fi% \if@anim@mk\else% \ifdefined\@anim@apdummy\else% empty appearance dummy \setbox\@anim@box=\hbox{\phantom{x}}% \@anim@xform{0}{0}{}{}{\@anim@box}% \xdef\@anim@apdummy{\@anim@lastxform}% \fi% \fi% \if@anim@js\@anim@upjscript{#1}{#2}\fi% JavaScript actions for ButtonUp events \setlength{\@anim@tmpdima}{\@anim@btnsize}% \@anim@pdfwid{\@anim@tmpdima}{\@anim@tmpdima}{\z@}{% /Subtype/Widget% \@anim@annotflag% /FT/Btn/Ff \if@anim@js 65536\else 65537\fi% /H\if@anim@js/I\else/N\fi% /BS <>% \if@anim@mk% /AP <>% /MK <>>>% \else% /AP <>% /MK <>>>% \fi% /T (#1.#2)% \@anim@tooltip% \if@anim@js/A <>\fi% }% \if@anim@js% \hbox to \@anim@tmpdima {% \vrule width 0pt height \@anim@tmpdima depth 0pt% \hss% }% \fi% } \newboolean{@anim@pauseframes} % true if \newframe* is being used \newboolean{@anim@chfps} % true if \newframe or \newframe* is being used % with optional `new frame rate' argument \newboolean{@anim@usrjs} % true if user JavaScript provided by user \newcount\@anim@skipfram % counter for skipped frames %user environment for animating inline graphics % #1: options % #2: frame rate (fps) \newenvironment{animateinline}[2][]{% \@anim@endsanitize% \leavevmode% \@anim@reset% to default settings \begingroup% \@anim@beginLTR% \ifcsname Ginput@path\endcsname% make use of graphic[xs] search path \let\input@path\Ginput@path% \fi% \setkeys{anim@user}{#1}% \ifthenelse{\boolean{@anim@autoplay}\OR\boolean{@anim@autoresume}}{% \setboolean{@anim@autoplayorresume}{true}% }{}% \ifthenelse{\NOT\boolean{@anim@controls}\AND\boolean{@anim@step}}{% \setboolean{@anim@loop}{true}% }{}% \if@anim@step% %for stepping animations, ignore any `controls' settings except \setboolean{@anim@controls@play}{false}% `step' and `stop' \setboolean{@anim@controls@speed}{false}% \setboolean{@anim@controls}{false}% \if@anim@controls@stop\setboolean{@anim@controls}{true}\fi% \if@anim@controls@step\setboolean{@anim@controls}{true}\fi% \fi% \global\@anim@curframe@zb=\z@% \global\@anim@skipfram=\z@% \if@anim@draft\else% %create button faces if necessary \if@anim@controls% \ifcsname btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape\endcsname\else% \@anim@makebuttons{\the\@anim@num}% \@anim@newkey{% btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape}{\the\@anim@num}% \fi% \fi% \if@anim@step\else% \xdef\@anim@nfps{-1}% \@anim@processfpsarg{#2}% \fi% \fi% \ifdefined\NoHyper\NoHyper\fi% silently suppress any hyperref specials \let\newframe\@anim@@newframe% \let\multiframe\@anim@multiframe% \@anim@beginframe% \ignorespaces% }{% \unskip% \@anim@endframe{\the\@anim@num}{\the\@anim@curframe@zb}% \ifdefined\endNoHyper\endNoHyper\fi% \global\advance\@anim@curframe@zb by \@ne% \if@anim@draft\else% \xdef\@anim@frames{\the\@anim@curframe@zb}% total number \global\@anim@tmpcnt=\@anim@frames% \global\advance\@anim@tmpcnt by -\@ne% \xdef\@anim@maxframe{\the\@anim@tmpcnt}% highest frame index %build timeline from optional timeline file \@anim@sanitizeJS% \if@anim@timeline\@anim@buildtmln{\the\@anim@num}\fi% %insert animation widget & controls \@anim@insertwidgets{\the\@anim@num}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour\@anim@lscape}}% \@anim@endsanitize% % if last frame used as poster, write frame num to aux file \ifnum\@anim@poster=\@anim@mone\relax% \@anim@keytoaux{a\the\@anim@num.poster}{\@anim@maxframe}% \fi% \fi% \@anim@endLTR% \endgroup% \global\advance\@anim@num by \@ne% } \let\@anim@animateinline\animateinline \def\animateinline{\@anim@sanitizeColon\@anim@animateinline} %usercommand for use within `animateinline' environment; %terminates the current frame and starts a new one \def\@anim@@newframe{% aliased to \newframe inside `animateinline' \unskip% \@anim@endframe{\the\@anim@num}{\the\@anim@curframe@zb}% \@ifstar\@anim@newframestar\@anim@newframe% } \def\@anim@processfpsarg#1{% %process frame rate argument \xdef\@anim@pfps{\@anim@nfps}% \xdef\@anim@nfps{#1\space}% \xdef\@anim@nfps{\expandafter\zap@space\@anim@nfps\@empty}% \ifx\@anim@nfps\@empty% no change of frame rate \xdef\@anim@nfps{\@anim@pfps}% \fi% \ifnum\@anim@curframe@zb=\z@\relax% \xdef\@anim@fps{\@anim@nfps}% default fps \xdef\@anim@nfpsat{\@anim@nfps}% \else% \xdef\@anim@nfpsat{\@anim@nfpsat,\@anim@nfps}% \fi% \ifdim\@anim@nfps\p@=\@anim@pfps\p@\else% \ifnum\@anim@curframe@zb=\z@\relax\else% \setboolean{@anim@chfps}{true}% change fps \fi% \fi% \ifdim\@anim@nfps\p@<\z@% \PackageError{animate}{% Negative frame rate `\@anim@nfps' is not allowed% }{}% \fi% }% \newcommand{\@anim@newframe}[1][]{% #1: new frame rate \ifnum\@anim@skipfram=\z@\relax% \global\advance\@anim@curframe@zb by \@ne% \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %process frame rate argument \@anim@processfpsarg{#1}% \fi% \fi% \fi% \fi% \@anim@beginframe% \ignorespaces% } \newcommand{\@anim@newframestar}[1][]{% starred variant for pausing animation \ifnum\@anim@skipfram=\z@\relax% #1: new frame rate \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %build JavaScript commands to fill the `pauseAt' array \xdef\@anim@pauseat{% \@anim@pauseat% a\the\@anim@num_pauseAt[\the\@anim@curframe@zb]=1;% }% \setboolean{@anim@pauseframes}{true}% \fi% \fi% \fi% \global\advance\@anim@curframe@zb by \@ne% \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %process frame rate argument \@anim@processfpsarg{#1}% \fi% \fi% \fi% \fi% \@anim@beginframe% \ignorespaces% } %starts new frame \def\@anim@beginframe{% \begingroup% \lrbox{\@anim@box}% store graphics in a box \ifdefined\@anim@curTxtDir\textdir\@anim@curTxtDir\fi% \@anim@begin% } %terminates current frame \def\@anim@endframe#1#2{% \@anim@end% \endlrbox% \endgroup% \ifnum\@anim@skipfram=\z@\relax% \ifnum#2=\z@\relax% \ifdim\wd\@anim@box=\z@% \PackageError{animate}{% Contents of first frame must not have zero width% }{% Possible reason: \protect\begin{animateinline}{...} immediately followed by \protect\newframe% }% \fi% \ifdim\ht\@anim@box=\z@\ifdim\dp\@anim@box=\z@% \PackageError{animate}{% Contents of first frame must not have zero height% }{}% \fi\fi% %draw draftbox according to dimensions of the first frame \if@anim@draft% \@anim@scale{\@anim@box}% \@anim@draftbox% \fi% \else% remaining frames %deal with zero width or totalheight boxes \ifdim\wd\@anim@box=\z@\global\setbox\@anim@box=\hbox{\phantom{X}}\fi% \ifdim\ht\@anim@box=\z@\ifdim\dp\@anim@box=\z@% \global\setbox\@anim@box=\hbox{\phantom{X}}% \fi\fi% \fi% %now create Form XObject of box contents \if@anim@draft\else% \@anim@xinline{#1}{#2}{\@anim@box}{!}% \fi% \fi% \global\advance\@anim@skipfram by \@ne% \ifnum\@anim@skipfram=\@anim@every\relax% \global\@anim@skipfram=\z@% \fi% } %user command for building loops around parameterized frame content, somewhat %like \multido (package multido) with embedded \newframe \newcount\@anim@mulframecnt %takes current loop No. of \multiframe \newboolean{@anim@insidemulti} % for checking whether we are inside \multiframe \setboolean{@anim@insidemulti}{false} \newcommand{\@anim@multiframe}[3]{% % aliased to \multiframe inside `animateinline' % #1: #repetitions, #2: vars, #3: frame content \unskip% \if@anim@insidemulti% \PackageError{animate}{\protect\multiframe\space cannot be nested}{}% \fi% \setboolean{@anim@insidemulti}{true}% %reset macro for updating variables \gdef\@anim@updatevars{}% %reset loop counter \global\@anim@mulframecnt=\z@% %remove spaces from variable declaration list (2nd arg) \xdef\@anim@vardecls{#2\space}% \xdef\@anim@vardecls{\expandafter\zap@space\@anim@vardecls\@empty}% \ifnum#1<\z@\relax% \PackageError{animate}{% \protect\multiframe: first argument must be greater than zero% }{}% \fi% %parse list of variable declarations and build macro for updating them \expandafter\@anim@parsevars\@anim@vardecls,\@nil% \whiledo{\@anim@mulframecnt<#1}{% \ifnum\@anim@mulframecnt>\z@\relax% \@anim@@newframe% \@anim@updatevars% update variables \fi% \global\advance\@anim@mulframecnt by \@ne% \ignorespaces% #3% execute loop body \unskip% }% \setboolean{@anim@insidemulti}{false}% \ignorespaces% } %splits list of variable declarations \def\@anim@parsevars#1,#2\@nil{% \ifthenelse{\equal{#1}{}}{}{\@anim@parsedecl#1\@nil=+\@nil\relax}% \ifthenelse{\equal{#2}{}}{}{\@anim@parsevars#2\@nil}% } %parser for single variable declaration \def\@anim@parsedecl#1=#2+#3\@nil#4\relax{% \ifx\@empty#4\@empty% \PackageError{animate}{\protect\multiframe: bad variable declaration}{}% \fi% \ifthenelse{\equal{#1}{}\OR\equal{#2}{}\OR\equal{#3}{}}{% \PackageError{animate}{\protect\multiframe: bad variable declaration}{}% }{}% \edef\@anim@vartype{\@anim@getvartype#1\@nil}% \ifthenelse{\equal{\@anim@vartype}{d}\OR\equal{\@anim@vartype}{D}}{% % dimensions, prefix d, D %initialize variable \setlength{\@anim@tmpdima}{#2}% \expandafter\edef\csname#1\endcsname{\number\@anim@tmpdima sp}% %global copy that saves current variable value between loops \expandafter\xdef\csname#1@old\endcsname{\number\@anim@tmpdima sp}% \setlength{\@anim@tmpdimb}{#3}% %global copy of increment \expandafter\xdef\csname#1@inc\endcsname{\number\@anim@tmpdimb sp}% %append script for updating variable to \@anim@updatevars macro \g@addto@macro\@anim@updatevars{% %new value \setlength{\@anim@tmpdima}{\csname#1@old\endcsname}% \addtolength{\@anim@tmpdima}{\csname#1@inc\endcsname}% \expandafter\edef\csname#1\endcsname{\number\@anim@tmpdima sp}% %global copy \expandafter\xdef\csname#1@old\endcsname{\number\@anim@tmpdima sp}% }% }{% \ifthenelse{% \equal{\@anim@vartype}{n}\OR\equal{\@anim@vartype}{N}% \OR\equal{\@anim@vartype}{r}\OR\equal{\@anim@vartype}{R}% }{% real numbers, prefix n, N, r, R %initialize variable \expandafter\edef\csname#1\endcsname{\@anim@fpeval{#2}}% %global copy that saves current variable value between loops \expandafter\xdef\csname#1@old\endcsname{\@anim@fpeval{#2}}% %append script for updating variable to \@anim@updatevars macro \g@addto@macro\@anim@updatevars{% %new value \expandafter\edef\csname#1\endcsname{% \@anim@fpeval{#3+\csname#1@old\endcsname}% }% %global copy \expandafter\xdef\csname#1@old\endcsname{\csname#1\endcsname}% }% }{% \ifthenelse{\equal{\@anim@vartype}{i}\OR\equal{\@anim@vartype}{I}}{% % integers, prefix i, I %initialize variable \setcounter{@anim@ltxcnt}{#2}% \expandafter\edef\csname#1\endcsname{\the@anim@ltxcnt}% %global copy that saves current variable value between loops \expandafter\xdef\csname#1@old\endcsname{\the@anim@ltxcnt}% \setcounter{@anim@ltxcnt}{#3}% %global copy of increment \expandafter\xdef\csname#1@inc\endcsname{\the@anim@ltxcnt}% %append script for updating variable to \@anim@updatevars macro \g@addto@macro\@anim@updatevars{% %new value \expandafter\global\expandafter\@anim@tmpcnt\csname#1@old\endcsname% \global\advance\@anim@tmpcnt by \csname#1@inc\endcsname% \expandafter\edef\csname#1\endcsname{\the\@anim@tmpcnt}% %global copy \expandafter\xdef\csname#1@old\endcsname{\the\@anim@tmpcnt}% }% }{% \PackageError{animate}{% \protect\multiframe: wrong name prefix `\@anim@vartype' in% \MessageBreak variable `#1'.\MessageBreak% Use any of d, D (dimensions), i, I (integer numbers)\MessageBreak% or n, N, r, R (real numbers) as the first letter to\MessageBreak% specify the variable type% }{}% }% }% }% } %get initial letter from variable name (the variable type, as with \multido) \def\@anim@getvartype#1#2\@nil{#1}% %prints zero padded integers % #1: arbitrary integer number as template specifying the % width, e. g. `987654' for a width of 6 digits % #2: the number to be formatted \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 (string of zeros) from given num \ifnum10#1>1#2 #1% \else% \@anim@template{0#1}{#2}% \fi% }% \begingroup\catcode`\_=13\let_\space \xdef\@anim@nusewarning{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak% @_There_were_unused_animation_transparencies._____@\MessageBreak% @_See_the_transcript_file_________________________@\MessageBreak% @___``\jobname.log''\MessageBreak% @_for_additional_information!_____________________@\MessageBreak% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% } \endgroup %macros for sanitizing characters \def\@anim@sanitize#1#2\@nil{% \catcode`#1=12% \ifx\@empty#2\@empty\else% \@anim@sanitize#2\@nil% \fi% } \def\@anim@sanitizeJS{% sanitize JS code while being read from timeline file \begingroup% \@anim@sanitize.:;?!/"'*+,->=<$\&@][)(^_`|~\#\@nil% \def\\{\string\\}% \def\{{\string\{}% \def\}{\string\}}% \def\%{\string\%}% } \def\@anim@sanitizeColon{% sanitize colon (`:') while reading the option list, \begingroup% in particular the `buttonfg' and `buttonbg' options \@anim@sanitize:\@nil% arguments } \let\@anim@endsanitize\endgroup %building timeline from timeline file \newread\@anim@@tmlnfile \newboolean{@anim@eof} \newcount\@anim@tmpcnt %scratch counter for different uses \newcounter{@anim@ltxcnt} %scratch LaTeX counter for different uses \newcount\@anim@curlayer %takes the number of the current layer being processed \newcount\@anim@lineno %current input line No. \newcount\@anim@curfield %current field of input line processed \def\@anim@buildtmln#1{% #1:@anim@num \endlinechar=-1% suppress trailing space at input line end \global\@anim@curframe@zb=\z@% %read timeline file a first time to get number of lines (= number of frames) \openin\@anim@@tmlnfile=\@anim@tmlnfile% \read\@anim@@tmlnfile to \@anim@inputline% \edef\@anim@inputline{\@anim@inputline\space}% %remove all spaces from input line \edef\@anim@inputline{\expandafter\zap@space\@anim@inputline\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% \whiledo{\NOT\boolean{@anim@eof}}{% \ifthenelse{\equal{\@anim@inputline}{}}{}{% %initialise contents & transparency lists for each frame \@anim@newkey{trlst@\the\@anim@curframe@zb}{}% \@anim@newkey{frmcontent@\the\@anim@curframe@zb}{}% \global\advance\@anim@curframe@zb by \@ne% }% \read\@anim@@tmlnfile to \@anim@inputline% \edef\@anim@inputline{\@anim@inputline\space}% \edef\@anim@inputline{\expandafter\zap@space\@anim@inputline\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% }% \closein\@anim@@tmlnfile% \xdef\@anim@transp{\@anim@frames}% total number of transparencies \xdef\@anim@frames{\the\@anim@curframe@zb}%total number of actual frames \global\@anim@tmpcnt=\@anim@frames% \global\advance\@anim@tmpcnt by -\@ne% \xdef\@anim@maxframe{\the\@anim@tmpcnt}% highest frame index \global\@anim@curframe@zb=\z@% \gdef\@anim@maxlayer{0}% highest layer index %reopen timeline file and build timeline \openin\@anim@@tmlnfile=\@anim@tmlnfile% \global\@anim@lineno=\z@% \read\@anim@@tmlnfile to \@anim@inputline% \edef\@anim@inputlinenospc{\@anim@inputline\space}% \edef\@anim@inputlinenospc{% \expandafter\zap@space\@anim@inputlinenospc\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% \message{\@anim@maxlayer\relax\else% \@anim@newkey{frmcontent@\the\@anim@curframe@zb}{% \@anim@getkeyval{frmcontent@\the\@anim@curframe@zb}% \@anim@getkeyval{% layercontent@\the\@anim@curframe@zb.\the\@anim@curlayer}% }% \@anim@newkey{trlst@\the\@anim@curframe@zb}{% \@anim@getkeyval{trlst@\the\@anim@curframe@zb}% \@anim@getkeyval{% layertrlst@\the\@anim@curframe@zb.\the\@anim@curlayer}% }% \@anim@newkey{% layercontent@\the\@anim@curframe@zb.\the\@anim@curlayer}{}% \@anim@newkey{% layertrlst@\the\@anim@curframe@zb.\the\@anim@curlayer}{}% \global\advance\@anim@curlayer by \@ne% \repeat% %detect multiple inclusion of the same transp. in the current frame \edef\@anim@trlst{% \the\@anim@curframe@zb.\@anim@getkeyval{trlst@\the\@anim@curframe@zb}}% \expandafter\@anim@findmult\@anim@trlst,\@nil% %insert frame Widget \@anim@makeframe{#1}{\the\@anim@curframe@zb}% %clean-up \expandafter\@anim@resetmult\@anim@trlst,\@nil% \@anim@newkey{trlst@\the\@anim@curframe@zb}{}% \@anim@newkey{frmcontent@\the\@anim@curframe@zb}{}% \message{.}% \global\advance\@anim@curframe@zb by \@ne% }% \read\@anim@@tmlnfile to \@anim@inputline% \edef\@anim@inputlinenospc{\@anim@inputline\space}% \edef\@anim@inputlinenospc{% \expandafter\zap@space\@anim@inputlinenospc\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% }% \message{\the\@anim@curframe@zb\space frames built}% \closein\@anim@@tmlnfile% %check for unused transparencies \global\@anim@tmpcnt=\z@% \loop\ifnum\@anim@transp>\@anim@tmpcnt\relax% \ifcsname u@tr\the\@anim@tmpcnt\endcsname% {\expandafter\global\expandafter\let\csname u@tr\the\@anim@tmpcnt\endcsname\@undefined}% \else% \PackageWarning{animate}{% Transparency \the\@anim@tmpcnt\space has never been used\MessageBreak% in the current animation.\MessageBreak% Timeline ``\@anim@tmlnfile'',\MessageBreak\jobname.tex% }% \ifcsname @anim@nusewarned\endcsname\else% \AtEndDocument{% \PackageWarningNoLine{animate}{\@anim@nusewarning}% }% \gdef\@anim@nusewarned{}% \fi% \fi% \global\advance\@anim@tmpcnt by \@ne% \repeat% \message{>}% } %reads one line of timeline file and splits into its colon separated parts \def\@anim@parseline#1:#2\@nil{% \ifcase\@anim@curfield\relax% %first field: a star (pause frame) \if@anim@step\else% \edef\@anim@tmp{#1\space}% \edef\@anim@tmp{\expandafter\zap@space\@anim@tmp\@empty}% \ifthenelse{\equal{\@anim@tmp}{*}}{% \xdef\@anim@pauseat{% \@anim@pauseat% a\the\@anim@num_pauseAt[\the\@anim@curframe@zb]=1;% }% \setboolean{@anim@pauseframes}{true}% }{}% \fi% \global\advance\@anim@curfield by \@ne% \@anim@parseline#2\@nil% \or% \if@anim@step\else% %second field: new frame rate \@anim@processfpsarg{#1}% \fi% \global\advance\@anim@curfield by \@ne% \@anim@parseline#2\@nil% \or% %parse the third field (list of layer specifications) \global\@anim@curlayer=\z@% \edef\@anim@tmp{#1\space}% \edef\@anim@tmp{\expandafter\zap@space\@anim@tmp\@empty}% \expandafter\@anim@parsethird\@anim@tmp;\@nil% \edef\@anim@tmp{#2\space}% \edef\@anim@tmp{\expandafter\zap@space\@anim@tmp\@empty}% %fourth field: JavaScript provided by the user \ifx\@anim@tmp\empty\else\@anim@parseforth#2\@nil\fi% \fi% } %parses frame contents specification (semicolon separated list of layer %specifications) \def\@anim@parsethird#1;#2\@nil{% \ifthenelse{\equal{#1}{}}{}{\@anim@parselayer#1,\@nil}%process one layer spec \ifthenelse{\equal{#2}{}}{}{% \global\advance\@anim@curlayer by \@ne% \ifnum\@anim@curlayer>\@anim@maxlayer\relax% \xdef\@anim@maxlayer{\the\@anim@curlayer}% \fi% \@anim@parsethird#2\@nil% }% } %process JavaScript field \def\@anim@parseforth#1:\@nil{% \edef\@anim@tmp{#1\space}% \edef\@anim@tmp{\expandafter\zap@space\@anim@tmp\@empty}% \ifx\@anim@tmp\@empty\else% \xdef\@anim@usrjsat{% \@anim@usrjsat% var a\the\@anim@num_usrJSat_\the\@anim@curframe@zb=function(){#1};% }% \setboolean{@anim@usrjs}{true}% \fi% } %parses contents of one layer specification (comma separated list of transp. %specs) \def\@anim@parselayer#1,#2\@nil{% \ifthenelse{\equal{#1}{}}{}{\@anim@process#1x\@nil}%process one transp spec \ifthenelse{\equal{#2}{}}{}{\@anim@parselayer#2\@nil}% } %process transparency spec, such as `123' or `456x78' or `9x0' or `c' (clear %transparency stack) \def\@anim@process#1x#2\@nil{% %determine number of repetitions of current transparency \ifthenelse{\equal{#2}{}}{% \gdef\@anim@repeats{1}% }{% \@anim@getrepetitions#2\@nil% }% \ifnum\@anim@repeats=\z@\relax% =0 means: repeat until end of timeline \edef\@anim@repeatuntil{\@anim@frames}% \else% \global\@anim@tmpcnt=\@anim@curframe@zb% \global\advance\@anim@tmpcnt by \@anim@repeats% \ifnum\@anim@frames<\@anim@tmpcnt\relax% \edef\@anim@repeatuntil{\@anim@frames}% \else% \edef\@anim@repeatuntil{\the\@anim@tmpcnt}% \fi% \fi% %test whether transparency stack of the current layer is to be cleared \ifthenelse{\equal{#1}{c}\OR\equal{#1}{C}}{% \global\@anim@tmpcnt=\@anim@curframe@zb% \loop\ifnum\@anim@frames>\@anim@tmpcnt\relax% %clear layer content \@anim@newkey{layercontent@\the\@anim@tmpcnt.\the\@anim@curlayer}{}% %clear list of transparencies used in the current layer \@anim@newkey{layertrlst@\the\@anim@tmpcnt.\the\@anim@curlayer}{}% \global\advance\@anim@tmpcnt by \@ne% \repeat% }{% %build contents of animation layer according to transparency specifications \ifnum\@anim@transp<#1\relax\else% ignore non-existing \ifnum\@anim@transp=#1\relax\else% transparencies \global\@anim@tmpcnt=\@anim@curframe@zb% \loop\ifnum\@anim@repeatuntil>\@anim@tmpcnt\relax% %layer content \edef\@anim@tmpvar{\@anim@getkeyval{% layercontent@\the\@anim@tmpcnt.\the\@anim@curlayer}}% \@anim@newkey{layercontent@\the\@anim@tmpcnt.\the\@anim@curlayer}{% \@anim@tmpvar\@anim@getkeyval{img@#1},% }% %append transp. to list of transparencies used in the current layer \edef\@anim@tmpvar{\@anim@getkeyval{% layertrlst@\the\@anim@tmpcnt.\the\@anim@curlayer}}% \@anim@newkey{layertrlst@\the\@anim@tmpcnt.\the\@anim@curlayer}{% \@anim@tmpvar#1,}% \global\advance\@anim@tmpcnt by \@ne% \repeat% \fi% \fi% }% } %get number of repetitions of frame \def\@anim@getrepetitions#1x\@nil{% \gdef\@anim@repeats{#1}% } \begingroup\catcode`\_=13\let_\space \xdef\@anim@multwarning{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak% @_In_certain_animation_frames,_transparencies_were_@\MessageBreak% @_included_multiple_times._This_may_considerably___@\MessageBreak% @_slow_down_animation_speed._Revise_the_timeline___@\MessageBreak% @_file_of_the_corresponding_animation!_____________@\MessageBreak% @__________________________________________________@\MessageBreak% @_See_the_transcript_file__________________________@\MessageBreak% @___``\jobname.log''\MessageBreak% @_for_additional_information_about_which_anima-____@\MessageBreak% @_tion(s)_are_affected!____________________________@\MessageBreak% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% }% \endgroup %detects multiple inclusion of the same transparency \def\@anim@findmult#1.#2,#3\@nil{% \ifthenelse{\equal{#2}{}}{}{% \@anim@newkey{u@tr#2}{}% mark current transp. as `used' \ifcsname m@tr#2\endcsname% \PackageWarning{animate}{% Transparency #2 more than once included in frame #1.% \MessageBreak% Timeline ``\@anim@tmlnfile'' on input line \the\@anim@lineno,% \MessageBreak\jobname.tex% }% \ifcsname @anim@multwarned\endcsname\else% \AtEndDocument{% \PackageWarningNoLine{animate}{\@anim@multwarning}% }% \gdef\@anim@multwarned{}% \fi% \else% {\expandafter\xdef\csname m@tr#2\endcsname{}}% \fi% }% \ifthenelse{\equal{#3}{}}{}{% \@anim@findmult#1.#3\@nil% }% } %reset transparency list \def\@anim@resetmult#1.#2,#3\@nil{% \ifthenelse{\equal{#2}{}}{}{% {\expandafter\global\expandafter\let\csname m@tr#2\endcsname\@undefined}% }% \ifthenelse{\equal{#3}{}}{}{% \@anim@resetmult#1.#3\@nil% }% } %command options \define@key{anim@user}{label}{% \gdef\@anim@label{#1}% \ifcsname @anim@#1\endcsname% \PackageWarning{animate}{Label #1 multiply defined} \ifdefined\@anim@multlabel\else \gdef\@anim@multlabel{}% \AtEndDocument{% \PackageWarningNoLine{animate}{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak @ There were multiply-defined labels! @\MessageBreak @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% }% \fi% \fi% \expandafter\gdef\csname @anim@#1\endcsname{}% } %setting the widget size \define@key{anim@user}{width}{% \gdef\@anim@widtharg{#1}% \ifdefined\@anim@usrwd\else% \global\advance\@anim@resizeflags by 4% \def\@anim@usrwd{}% \fi% } \define@key{anim@user}{height}{% \gdef\@anim@heightarg{#1}% \ifdefined\@anim@usrht\else% \global\advance\@anim@resizeflags by 2% \def\@anim@usrht{}% \fi% } \define@key{anim@user}{totalheight}{% \gdef\@anim@totheightarg{#1}% \ifdefined\@anim@usrtht\else% \global\advance\@anim@resizeflags by \@ne% \def\@anim@usrtht{}% \fi% } \define@key{anim@user}{depth}{% \PackageWarning{animate}{Ignoring obsolete `depth' option.}% } \newboolean{@anim@iso} \define@key{anim@user}{keepaspectratio}[true]{% \setboolean{@anim@iso}{#1}% } \define@key{anim@user}{scale}{% \gdef\@anim@boxscale{#1}% } \define@key{anim@user}{buttonsize}{% \gdef\@anim@btnsize{#1}% } \def\@anim@colours#1:#2\@nil{% helper macro to get number of colour components \xdef\@anim@colour{\@anim@colour\space #1}% and to replace : by ` ' in the arg \ifthenelse{\equal{#2}{}}{}{% \global\advance\@anim@tmpcnt by \@ne% \@anim@colours#2\@nil% }% } \define@key{anim@user}{buttonbg}{%background colour of buttons \global\@anim@tmpcnt=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:\@nil% \xdef\@anim@bgcolour{\@anim@colour}% \if@anim@dvips% \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@bg{\@anim@colour\space setgray}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@bg{\@anim@colour\space setrgbcolor}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@bg{\@anim@colour\space setcmykcolor}% \fi% \fi% \fi% \else% pdftex and dvipdfmx \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@bg{\@anim@colour\space g}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@bg{\@anim@colour\space rg}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@bg{\@anim@colour\space k}% \fi% \fi% \fi% \fi% } \define@key{anim@user}{buttonfg}{%stroking colour of buttons \global\@anim@tmpcnt=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:\@nil% \xdef\@anim@fgcolour{\@anim@colour}% \if@anim@dvips% \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@fg{\@anim@colour\space setgray}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@fg{\@anim@colour\space setrgbcolor}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@fg{\@anim@colour\space setcmykcolor}% \fi% \fi% \fi% \else% pdftex and dvipdfmx \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@fg{\@anim@colour\space G}% \xdef\@anim@@@fg{\@anim@colour\space g}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@fg{\@anim@colour\space RG}% \xdef\@anim@@@fg{\@anim@colour\space rg}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@fg{\@anim@colour\space K}% \xdef\@anim@@@fg{\@anim@colour\space k}% \fi% \fi% \fi% \fi% } \define@key{anim@user}{buttonalpha}{%button opacity \xdef\@anim@alpha{#1}% } \newboolean{@anim@controls} \newboolean{@anim@controls@play} \newboolean{@anim@controls@step} \newboolean{@anim@controls@stop} \newboolean{@anim@controls@speed} \def\@anim@user@controls@all{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@play}{true}% \setboolean{@anim@controls@step}{true}% \setboolean{@anim@controls@stop}{true}% \setboolean{@anim@controls@speed}{true}% } \def\@anim@user@controls@none{% \setboolean{@anim@controls}{false}% \setboolean{@anim@controls@play}{false}% \setboolean{@anim@controls@step}{false}% \setboolean{@anim@controls@stop}{false}% \setboolean{@anim@controls@speed}{false}% } \define@key{anim@user}{controls}[all]{% \@anim@user@controls@none% \setkeys{anim@user@controls}{#1}% } \define@key{anim@user@controls}{all}[]{\@anim@user@controls@all} \define@key{anim@user@controls}{true}[]{\@anim@user@controls@all} \define@key{anim@user@controls}{on}[]{\@anim@user@controls@all} \define@key{anim@user@controls}{none}[]{\@anim@user@controls@none} \define@key{anim@user@controls}{false}[]{\@anim@user@controls@none} \define@key{anim@user@controls}{off}[]{\@anim@user@controls@none} \define@key{anim@user@controls}{play}[]{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@play}{true}% } \define@key{anim@user@controls}{step}[]{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@step}{true}% } \define@key{anim@user@controls}{stop}[]{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@stop}{true}% } \define@key{anim@user@controls}{speed}[]{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@speed}{true}% } \newboolean{@anim@loop} \define@key{anim@user}{loop}[true]{% \setboolean{@anim@loop}{#1}% } \newboolean{@anim@autoplay} \define@key{anim@user}{autoplay}[true]{% \setboolean{@anim@autoplay}{#1}% \if@anim@autoplay% \setboolean{@anim@autoresume}{false}% \fi% } \newboolean{@anim@autoresume} \define@key{anim@user}{autoresume}[true]{% \setboolean{@anim@autoresume}{#1}% \if@anim@autoresume% \setboolean{@anim@autoplay}{false}% \fi% } \newboolean{@anim@autopause} \define@key{anim@user}{autopause}[true]{% \setboolean{@anim@autopause}{#1}% } \newboolean{@anim@palindrome} \define@key{anim@user}{palindrome}[true]{% \setboolean{@anim@palindrome}{#1}% } \def\@anim@mone{-1}\def\@anim@mtwo{-2} \define@key{anim@user}{poster}[first]{% | first | last | none \ifthenelse{% \equal{#1}{first}% }{% \gdef\@anim@poster{0}% }{% \ifthenelse{% \equal{#1}{last}% }{% \gdef\@anim@poster{-1}% }{% \ifthenelse{% \equal{#1}{none}% }{% \gdef\@anim@poster{-2}% }{% \ifnum#1<\z@\relax% \PackageError{animate}{% Poster frame `#1' is out-of-bounds on\MessageBreak% input line \the\inputlineno.\MessageBreak% Try one of `poster=first' or `poster=none'% }{}% \fi% \gdef\@anim@poster{#1}% }% }% }% } \newboolean{@anim@step} \define@key{anim@user}{step}[true]{% \setboolean{@anim@step}{#1}% } \newboolean{@anim@draft} \define@key{anim@user}{draft}[true]{% \setboolean{@anim@draft}{#1}% } \define@key{anim@user}{final}[true]{% \ifthenelse{\equal{#1}{true}}{% \setboolean{@anim@draft}{false}% }{% \setboolean{@anim@draft}{true}% }% } \define@key{anim@user}{nomouse}[true]{% \ifthenelse{\equal{#1}{true}}{% \gdef\@anim@btnflag{65537}% }{}% } \define@key{anim@user}{timeline}{% \IfFileExists{#1}{% \xdef\@anim@tmlnfile{\expandafter\zap@finalspace\@filef@und\@nil}% \setboolean{@anim@timeline}{true}% }{% \PackageError{animate}{timeline file `#1' cannot be opened for reading% }{% Make sure file `#1' exists and is readable!% }% }% } \define@key{anim@user}{begin}{% \gdef\@anim@begin{#1}% } \define@key{anim@user}{end}{% \gdef\@anim@end{#1}% } \define@key{anim@user}{every}{% embed every #1th frame \ifnum#1<\@ne\relax\gdef\@anim@every{1}\else\gdef\@anim@every{#1}\fi% } \define@key{anim@user}{bb}{% \g@addto@macro\@anim@gropts{, bb=#1}% } \define@key{anim@user}{viewport}{% \g@addto@macro\@anim@gropts{, viewport=#1}% } \define@key{anim@user}{trim}{% \g@addto@macro\@anim@gropts{, trim=#1}% } \define@key{anim@user}{angle}{% \g@addto@macro\@anim@gropts{, angle=#1}% } \newboolean{@anim@meas} \define@key{anim@user}{measure}[true]{% \setboolean{@anim@meas}{#1}% } \define@key{anim@user}{method}{% \ifthenelse{\equal{#1}{icon}}{% \def\@anim@method{\z@}% }{% \ifthenelse{\equal{#1}{widget}}{% \def\@anim@method{\@ne}% }{% \ifthenelse{\equal{#1}{ocg}}{% \def\@anim@method{\tw@}% }{}% }% }% } \define@key{anim@user}{useocg}[]{% \PackageError{animate}{% Option `useocg' has been removed.\MessageBreak% Use `method=ocg' instead% }{}% } \define@key{anim@user}{type}{\gdef\@anim@ftype{#1}}% %macro to reset macros and booleans \def\@anim@reset{% \gdef\@anim@label{}% \xdef\@anim@boxscale{\@anim@@boxscale}% \global\let\if@anim@iso=\if@anim@@iso% \global\@anim@resizeflags\@anim@@resizeflags% \global\let\@anim@widtharg\@anim@@widtharg% \global\let\@anim@heightarg\@anim@@heightarg% \global\let\@anim@totheightarg\@anim@@totheightarg% \let\@anim@usrwd\@anim@pkgwd% \let\@anim@usrht\@anim@pkght% \let\@anim@usrtht\@anim@pkgtht% \xdef\@anim@bg{\@anim@@bg}% \xdef\@anim@fg{\@anim@@fg}% \xdef\@anim@@@fg{\@anim@@@@fg}% \xdef\@anim@bgcolour{\@anim@@bgcolour}% default button colours \xdef\@anim@fgcolour{\@anim@@fgcolour}% \global\let\@anim@alpha\@anim@@alpha% \xdef\@anim@btnsize{\@anim@@btnsize}% \xdef\@anim@poster{\@anim@@poster}% \global\let\if@anim@controls=\if@anim@@controls% \global\let\if@anim@controls@play=\if@anim@@controls@play% \global\let\if@anim@controls@step=\if@anim@@controls@step% \global\let\if@anim@controls@stop=\if@anim@@controls@stop% \global\let\if@anim@controls@speed=\if@anim@@controls@speed% \global\let\if@anim@loop=\if@anim@@loop% \global\let\if@anim@autoplay=\if@anim@@autoplay% \global\let\if@anim@autoresume=\if@anim@@autoresume% \global\let\if@anim@autopause=\if@anim@@autopause% \global\let\if@anim@palindrome=\if@anim@@palindrome% \global\let\if@anim@step=\if@anim@@step% \global\let\if@anim@draft=\if@anim@@draft% \xdef\@anim@method{\@anim@@method}% \global\let\@anim@btnflag=\@anim@@btnflag% \gdef\@anim@properties{}% \setboolean{@anim@pauseframes}{false}% \gdef\@anim@pauseat{}% \setboolean{@anim@chfps}{false}% \setboolean{@anim@usrjs}{false}% \gdef\@anim@nfpsat{}% \gdef\@anim@pfpsat{}% \gdef\@anim@usrjsat{}% \gdef\@anim@tmlnfile{}% \setboolean{@anim@timeline}{false}% \gdef\@anim@begin{}% \gdef\@anim@end{}% \gdef\@anim@every{1}% frames to be included \gdef\@anim@gropts{}% \setboolean{@anim@multipage}{false}% \setboolean{@anim@meas}{false}% \setboolean{@anim@autoplayorresume}{false}% \xdef\@anim@ftype{\@anim@@ftype}% } %package options \define@key{anim@pkg}{dvips}[]{% \ifthenelse{\equal{#1}{}}{}{% \PackageError{animate}{% Package option `dvips' does not accept arguments% }{}% }% }% \define@key{anim@pkg}{dvipdfmx}[]{ \ifthenelse{\equal{#1}{}}{}{% \PackageError{animate}{% Package option `dvipdfmx' does not accept arguments% }{}% }% }% \define@key{anim@pkg}{xetex}[]{ \ifthenelse{\equal{#1}{}}{}{% \PackageError{animate}{% Package option `xetex' does not accept arguments% }{}% }% }% \def\@anim@@bg{} \def\@anim@@bgcolour{} \define@key{anim@pkg}{buttonbg}{%background colour of buttons \global\@anim@tmpcnt=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:\@nil% \xdef\@anim@@bgcolour{\@anim@colour}% \if@anim@dvips% \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@@bg{\@anim@colour\space setgray}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@@bg{\@anim@colour\space setrgbcolor}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@@bg{\@anim@colour\space setcmykcolor}% \fi% \fi% \fi% \else% pdftex and dvipdfmx \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@@bg{\@anim@colour\space g}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@@bg{\@anim@colour\space rg}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@@bg{\@anim@colour\space k}% \fi% \fi% \fi% \fi% } \if@anim@dvips \def\@anim@@fg{0 setgray}\def\@anim@@@@fg{}% \else% pdftex and dvipdfmx \def\@anim@@fg{0 G}\def\@anim@@@@fg{0 g}% \fi \def\@anim@@fgcolour{} \define@key{anim@pkg}{buttonfg}{%stroking colour of buttons \global\@anim@tmpcnt=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:\@nil% \xdef\@anim@@fgcolour{\@anim@colour}% \if@anim@dvips% \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@@fg{\@anim@colour\space setgray}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@@fg{\@anim@colour\space setrgbcolor}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@@fg{\@anim@colour\space setcmykcolor}% \fi% \fi% \fi% \else% pdftex and dvipdfmx \ifnum\@anim@tmpcnt=\@ne\relax% \xdef\@anim@@fg{\@anim@colour\space G}% \xdef\@anim@@@@fg{\@anim@colour\space g}% \else% \ifnum\@anim@tmpcnt=3\relax% \xdef\@anim@@fg{\@anim@colour\space RG}% \xdef\@anim@@@@fg{\@anim@colour\space rg}% \else% \ifnum\@anim@tmpcnt=4\relax% \xdef\@anim@@fg{\@anim@colour\space K}% \xdef\@anim@@@@fg{\@anim@colour\space k}% \fi% \fi% \fi% \fi% } \def\@anim@@alpha{} \define@key{anim@pkg}{buttonalpha}{%button opacity \xdef\@anim@@alpha{#1}% } \newcount\@anim@@resizeflags \def\@anim@@widtharg{\width}% \define@key{anim@pkg}{width}{% \def\@anim@@widtharg{#1}% \ifdefined\@anim@pkgwd\else% \advance\@anim@@resizeflags by 4% \def\@anim@pkgwd{}% \fi% } \def\@anim@@heightarg{\height}% \define@key{anim@pkg}{height}{% \def\@anim@@heightarg{#1}% \ifdefined\@anim@pkght\else% \advance\@anim@@resizeflags by 2% \def\@anim@pkght{}% \fi% } \def\@anim@@totheightarg{\totalheight}% \define@key{anim@pkg}{totalheight}{% \def\@anim@@totheightarg{#1}% \ifdefined\@anim@pkgtht\else% \advance\@anim@@resizeflags by \@ne% \def\@anim@pkgtht{}% \fi% } \newboolean{@anim@@iso} \define@key{anim@pkg}{keepaspectratio}[true]{% \setboolean{@anim@@iso}{#1}% } \def\@anim@@boxscale{1}% \define@key{anim@pkg}{scale}{% \def\@anim@@boxscale{#1}% } \def\@anim@@btnsize{1.44em}% \define@key{anim@pkg}{buttonsize}{% \gdef\@anim@@btnsize{#1}% } \newboolean{@anim@@controls} \newboolean{@anim@@controls@play} \newboolean{@anim@@controls@step} \newboolean{@anim@@controls@stop} \newboolean{@anim@@controls@speed} \def\@anim@pkg@controls@all{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@play}{true}% \setboolean{@anim@@controls@step}{true}% \setboolean{@anim@@controls@stop}{true}% \setboolean{@anim@@controls@speed}{true}% } \def\@anim@pkg@controls@none{% \setboolean{@anim@@controls}{false}% \setboolean{@anim@@controls@play}{false}% \setboolean{@anim@@controls@step}{false}% \setboolean{@anim@@controls@stop}{false}% \setboolean{@anim@@controls@speed}{false}% } \define@key{anim@pkg}{controls}[all]{% \@anim@pkg@controls@none% \setkeys{anim@pkg@controls}{#1}% } \define@key{anim@pkg@controls}{all}[]{\@anim@pkg@controls@all} \define@key{anim@pkg@controls}{true}[]{\@anim@pkg@controls@all} \define@key{anim@pkg@controls}{on}[]{\@anim@pkg@controls@all} \define@key{anim@pkg@controls}{none}[]{\@anim@pkg@controls@none} \define@key{anim@pkg@controls}{false}[]{\@anim@pkg@controls@none} \define@key{anim@pkg@controls}{off}[]{\@anim@pkg@controls@none} \define@key{anim@pkg@controls}{play}[]{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@play}{true}% } \define@key{anim@pkg@controls}{step}[]{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@step}{true}% } \define@key{anim@pkg@controls}{stop}[]{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@stop}{true}% } \define@key{anim@pkg@controls}{speed}[]{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@speed}{true}% } \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}% } \gdef\@anim@@poster{0}% \define@key{anim@pkg}{poster}[first]{% \ifthenelse{% \equal{#1}{first}% }{% \gdef\@anim@@poster{0}% }{% \ifthenelse{% \equal{#1}{last}% }{% \gdef\@anim@@poster{-1}% }{% \ifthenelse{% \equal{#1}{none}% }{% \gdef\@anim@@poster{-2}% }{% \ifnum#1<\z@\relax% \PackageError{animate}{% Poster frame `#1' is out-of-bounds on\MessageBreak% input line \the\inputlineno.\MessageBreak% Try one of `poster=first' or `poster=none'% }{}% \fi% \gdef\@anim@@poster{#1}% }% }% }% } \newboolean{@anim@@step} \setboolean{@anim@@step}{false} \define@key{anim@pkg}{step}[true]{% \setboolean{@anim@@step}{#1}% } \newboolean{@anim@@draft} \ifdraft{%globally set by document class \setboolean{@anim@@draft}{true}% }{% \setboolean{@anim@@draft}{false}% }% \define@key{anim@pkg}{draft}[true]{% \setboolean{@anim@@draft}{#1}% } \define@key{anim@pkg}{final}[true]{% \ifthenelse{\equal{#1}{true}}{% \setboolean{@anim@@draft}{false}% }{% \setboolean{@anim@@draft}{true}% }% } \def\@anim@@btnflag{65536}% \define@key{anim@pkg}{nomouse}[true]{% \ifthenelse{\equal{#1}{true}}{% \gdef\@anim@@btnflag{65537}% }{}% } %file type (extension) of graphics files to be embedded \def\@anim@@ftype{}% \define@key{anim@pkg}{type}{\def\@anim@@ftype{#1}}% % animation method: icon vs. widget vs. ocg based \define@key{anim@pkg}{method}{% \ifthenelse{\equal{#1}{icon}}{% \def\@anim@@method{\z@}% }{% \ifthenelse{\equal{#1}{widget}}{% \def\@anim@@method{\@ne}% }{% \ifthenelse{\equal{#1}{ocg}}{% \def\@anim@@method{\tw@}% }{}% ignoring wrong input }% }% } \define@key{anim@pkg}{useocg}[]{% \PackageError{animate}{% Package option `useocg' has been removed.\MessageBreak% Use `method=ocg' instead% }{}% } %default animation method is Icon based \def\@anim@@method{\z@} %process package options \def\@anim@setpkgkeys#1{\setkeys{anim@pkg}{#1}} \edef\@anim@pkgopts{{\@ptionlist{\@currname.\@currext}}} \expandafter\@anim@setpkgkeys\@anim@pkgopts %JavaScript objects %animation widget's PageOpen/PageVisible event \def\@anim@pojscript#1{% \@anim@streamobj{}{\@anim@@pojscript{#1}}% \xdef\@anim@pojscriptobj{\@anim@lastobj}% } \def\@anim@@pojscript#1{% #1: @anim@num % console.show();% % console.clear();% if(typeof a#1_idx==='undefined'){% initialize animation var a#1_idx\ifnum\@anim@method>\z@,a#1_on=0\fi% \if@anim@step\else,a#1_int\fi;% %takes references to frame ocgs/Field objects belonging to the current %animation var a#1_fr=new Array();% %initialize fr properties \ifcase\@anim@method %icon based var a#1_wid=this.getField('anm#1');%reference to interactive widget for(i=0;i<=\@anim@maxframe;i++){% a#1_fr[i]=this.getField('#1.'+i).buttonGetIcon();% }% \ifnum\@anim@poster=\@anim@mtwo if(typeof blnk==='undefined'){% blank poster var blnk=this.getField('0000').buttonGetIcon();% }% \fi% \or %widget based %get array of animation frames for(i=0;i<=\@anim@maxframe;i++){% a#1_fr[i]=this.getField('#1.'+i);% }% \or %ocg based %get array of ocgs of current page ocg=this.getOCGs(this.pageNum);% for(i in ocg){% ocgName=ocg[i].name.split('.');% if(ocgName[0]==#1){% %get array of animation frames a#1_fr[ocgName[1]]=ocg[i];% %set basic frame state a#1_fr[ocgName[1]].state=ocg[i].initState;% }% }% \fi% \if@anim@controls@play var a#1_btnPauseLeft=this.getField('#1.PauseLeft');% var a#1_btnPlayLeft=this.getField('#1.PlayLeft');% var a#1_btnPauseRight=this.getField('#1.PauseRight');% var a#1_btnPlayRight=this.getField('#1.PlayRight');% \fi% %playing state and direction \if@anim@step% \if@anim@palindrome var a#1_playsRight=true;\fi% \else a#1_playsRight=true;% \fi var a#1_isPaused=false;% \if@anim@step\else var a#1_playing=false;% \if@anim@pauseframes %this array takes the frame numbers at which to pause playback var a#1_pauseAt=new Array();% \@anim@pauseat% \fi% \if@anim@chfps %arrays that take frame numbers (array index) and fps values var a#1_nFpsAt=new Array(\@anim@nfpsat);% \fi var a#1_fps=\@anim@fps==0?1e-6:\@anim@fps;% var a#1_spd=1;% var a#1_setFps=function(f){% a#1_fps=f==0?1e-6:f;% if(a#1_playing){% if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}% }% };% \fi% \if@anim@usrjs %array to take frame numbers (array index) and user provided JavaScript \@anim@usrjsat% \fi% %actions var a#1_seekFrame=function(f){% \ifnum\@anim@poster=\@anim@mtwo if(f<-1){% \ifcase\@anim@method %icon based a#1_wid.buttonSetIcon(blnk);% this.dirty=false;% \or %widget based a#1_on=0;% a#1_fr[0].display=display.hidden;% this.dirty=false;% \or %ocg based a#1_on=0;% a#1_fr[0].state=false;% \fi a#1_idx=-1;% }% \fi if(f>\@anim@maxframe||f<0){return -1;}% a#1_idx=f;% \if@anim@usrjs if(typeof this['a#1_usrJSat_'+f]!=='undefined'){% ret=app.setTimeOut(% execute JS in "parallel" 'try{a#1_usrJSat_'+f+'();}catch(e){console.println(e);}',1% );% }% \fi% \ifcase\@anim@method %icon based a#1_wid.buttonSetIcon(a#1_fr[f]);% this.dirty=false;% \or %widget based a#1_fr[a#1_on].display=display.hidden;% a#1_fr[f].display=display.visible;% a#1_on=f;% this.dirty=false;% \or %ocg based a#1_fr[a#1_on].state=false;% a#1_fr[f].state=true;% a#1_on=f;% \fi \if@anim@step\else% \if@anim@chfps if(a#1_nFpsAt[f]!=a#1_fps){% a#1_setFps(a#1_nFpsAt[f]);% }% \fi% \if@anim@meas a#1_frcnt++;\fi% \fi% return 0;% };% var a#1_stopFirst=function(){% \if@anim@step a#1_isPaused=false;% stop \else a#1_pause(true);% stop \fi a#1_seekFrame(0);% };% var a#1_stopLast=function(){% \if@anim@step a#1_isPaused=false;% stop \else a#1_pause(true);% stop \fi a#1_seekFrame(\@anim@maxframe);% };% var a#1_gotoNext=function(){% if(a#1_seekFrame(a#1_idx+1)<0){% \if@anim@step\else\if@anim@meas a#1_stopMeas();\fi\fi% \if@anim@palindrome% \if@anim@step a#1_stopLast();% a#1_playsRight=false;% \else if(a#1_playing){% a#1_seekFrame(a#1_idx-1);% a#1_playLeft();% }% \fi% \else% \if@anim@step a#1_stopLast();% \else% \if@anim@loop if(a#1_playing){% a#1_seekFrame(0);% a#1_setFps(\@anim@fps);% }else{a#1_stopLast();}% \else a#1_stopLast();% \fi% \fi% \fi return;% }% \if@anim@step\else% \if@anim@pauseframes if(a#1_playing&&a#1_pauseAt[a#1_idx]){a#1_pause();}% \fi% \fi% };% var a#1_gotoPrev=function(){% if(a#1_seekFrame(a#1_idx-1)<0){% \if@anim@step\else\if@anim@meas a#1_stopMeas();\fi\fi% \if@anim@palindrome% \if@anim@step a#1_stopFirst();% a#1_playsRight=true;% \else if(a#1_playing){% a#1_seekFrame(a#1_idx+1);% a#1_playRight();% }% \fi% \else% \if@anim@step a#1_stopFirst();% \else% \if@anim@loop if(a#1_playing){% a#1_seekFrame(\@anim@maxframe);% }else{a#1_stopFirst();}% \else a#1_stopFirst();% \fi% \fi% \fi return;% }% \if@anim@step\else% \if@anim@pauseframes if(a#1_playing&&a#1_pauseAt[a#1_idx]){a#1_pause();}% \fi% \fi% };% \if@anim@step\else var a#1_pause=function(stop){% try{app.clearInterval(a#1_int);}catch(e){}% a#1_playing=false;% a#1_isPaused=!stop;% \if@anim@controls@play a#1_btnPauseLeft.display=display.hidden;% a#1_btnPlayLeft.display=display.visible;% a#1_btnPauseRight.display=display.hidden;% a#1_btnPlayRight.display=display.visible;% this.dirty=false;% \fi% };% var a#1_playRight=function(){% \if@anim@meas a#1_startMeas();\fi try{tmp_int=app.setInterval('a#1_gotoNext()',% 1000/a#1_fps/a#1_spd);}catch(e){}% try{app.clearInterval(a#1_int);}catch(e){}% a#1_int=tmp_int;% a#1_playsRight=true;% a#1_playing=true;% a#1_isPaused=false;% \if@anim@controls@play a#1_btnPauseLeft.display=display.visible;% a#1_btnPlayLeft.display=display.hidden;% a#1_btnPauseRight.display=display.visible;% a#1_btnPlayRight.display=display.hidden;% this.dirty=false;% \fi% };% var a#1_playLeft=function(){% \if@anim@meas a#1_startMeas();\fi try{tmp_int=app.setInterval('a#1_gotoPrev()',% 1000/a#1_fps/a#1_spd);}catch(e){}% try{app.clearInterval(a#1_int);}catch(e){}% a#1_int=tmp_int;% a#1_playsRight=false;% a#1_playing=true;% a#1_isPaused=false;% \if@anim@controls@play a#1_btnPauseLeft.display=display.visible;% a#1_btnPlayLeft.display=display.hidden;% a#1_btnPauseRight.display=display.visible;% a#1_btnPlayRight.display=display.hidden;% this.dirty=false;% \fi% };% \if@anim@controls@speed var a#1_spdIncr=function(){% speed up animation a#1_spd*=1.1;% a#1_setFps(a#1_fps);% };% var a#1_spdDecr=function(){% slow down animation a#1_spd/=1.1;% a#1_setFps(a#1_fps);% };% var a#1_spdReset=function(){% reset to default speed a#1_spd=1;% a#1_setFps(a#1_fps);% };% \fi% \if@anim@meas spc=String.fromCharCode(32);% var a#1_frcnt,% frame counter for speed measurements a#1_msStart,% takes start time (in millisecs) a#1_msEnd;% takes end time (in millisecs) var a#1_startMeas=function(){% a#1_frcnt=1;% reset frame counter a#1_msStart=(new Date()).getTime();% };% var a#1_stopMeas=function(){% a#1_msEnd=(new Date()).getTime();% console.show();console.println(% 'av.'+spc+'frame'+spc+'rate:'+spc+% 1e3*a#1_frcnt/(a#1_msEnd-a#1_msStart)+spc+'fps'% );% };% \fi% \fi% \if@anim@step var a#1_stepBwd=function(){% a#1_seekFrame(a#1_idx-1);% a#1_isPaused=true;% };% var a#1_stepFwd=function(){% a#1_seekFrame(a#1_idx+1);% a#1_isPaused=true;% };% \else var a#1_stepBwd=function(){if(!a#1_playing){% a#1_seekFrame(a#1_idx-1);% a#1_isPaused=true;% }};% var a#1_stepFwd=function(){if(!a#1_playing){% a#1_seekFrame(a#1_idx+1);% a#1_isPaused=true;% }};% var a#1_playBwd=function(){% if(a#1_idx==0||!a#1_isPaused){a#1_stopLast();}% a#1_playLeft();% };% var a#1_playFwd=function(){% if(a#1_idx==\@anim@maxframe||!a#1_isPaused){a#1_stopFirst();}% a#1_playRight();% };% \fi% %animation API for labelled anims \ifx\empty\@anim@label\empty\else if(typeof anim==='undefined'){var anim=new Array();}% if(typeof anim['\@anim@label']==='undefined'){% anim['\@anim@label']={% \if@anim@step\else playBwd:a#1_playBwd,% playFwd:a#1_playFwd,% pause:a#1_pause,% get isPlaying(){return a#1_playing;},% get fps(){return a#1_fps;},% set fps(f){% if(f<0||isNaN(f)){% throw new RangeError('Frame_rate_not_in_allowed_range');% }else{a#1_setFps(f);}% },% get speed(){return a#1_spd;},% set speed(s){% if(s<=0||isNaN(s)){% throw new RangeError('Speed_factor_not_in_allowed_range');% }else{% a#1_spd=s;% a#1_setFps(a#1_fps);% }% },% get dt(){return 1000/a#1_fps/a#1_spd;},% get playsFwd(){return a#1_playsRight;},% \fi get numFrames(){return \@anim@frames;},% get frameNum(){return a#1_idx;},% set frameNum(f){% f=Math.floor(f);% if(f<0||f>\@anim@maxframe||isNaN(f)){% throw new RangeError('Frame_number_not_in_allowed_range');% }% \if@anim@step if(a#1_seekFrame(f)>-1)a#1_isPaused=true;% \else if(a#1_playing){% a#1_pause();a#1_seekFrame(f);% if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}% }else{if(a#1_seekFrame(f)>-1)a#1_isPaused=true;}% \fi% },% stopFirst:a#1_stopFirst,% stopLast:a#1_stopLast% };% }% \fi% %poster=none \ifnum\@anim@poster=\@anim@mtwo a#1_seekFrame(-2);\fi% %poster=|first \ifnum\@anim@poster>\@anim@mone a#1_seekFrame(\@anim@poster);\fi% %poster=last \ifnum\@anim@poster=\@anim@mone a#1_seekFrame(\@anim@maxframe);\fi% }% \if@anim@step\else% \if@anim@autoplayorresume% \if@anim@autoresume if(a#1_isPaused){% \fi if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}% \if@anim@autoresume% }% \fi% \fi% \fi% } %animation widget's PageClose and PageInvisible events \def\@anim@pcjscript#1{% \@anim@streamobj{}{\@anim@@pcjscript{#1}}% \xdef\@anim@pcjscriptobj{\@anim@lastobj}% } \def\@anim@@pcjscript#1{% #1: @anim@num \if@anim@step% \if@anim@palindrome a#1_playsRight=true;\fi% \else if(a#1_playing){ \if@anim@autopause a#1_pause();% \else a#1_pause(true);% stop \fi% } if(!a#1_isPaused)a#1_playsRight=true;% \fi %re-display poster frame if(!a#1_isPaused){% i.e. if stopped %poster=none \ifnum\@anim@poster=\@anim@mtwo a#1_seekFrame(-2);\fi% %poster=|first \ifnum\@anim@poster>\@anim@mone a#1_seekFrame(\@anim@poster);\fi% %poster=last \ifnum\@anim@poster=\@anim@mone a#1_seekFrame(\@anim@maxframe);\fi% }% } %other trigger events in the anim widget's AA dictionary \def\@anim@otherjscript#1{% \xdef\@anim@otherjscriptkey{% /D <>% /U <>% }% } %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}% \xdef\@anim@upjscriptstring{% app.focusRect=false;% \ifx\@anim@action\@anim@EndLeft a#1_stopFirst();% \else% \ifx\@anim@action\@anim@StepLeft a#1_stepBwd();% \else% \ifx\@anim@action\@anim@PlayPauseLeft if(a#1_playing){a#1_pause();}else{a#1_playBwd();}% \else% \ifx\@anim@action\@anim@PlayPauseRight if(a#1_playing){a#1_pause();}else{a#1_playFwd();}% \else% \ifx\@anim@action\@anim@StepRight a#1_stepFwd();% \else% \ifx\@anim@action\@anim@EndRight a#1_stopLast();% \else% \ifx\@anim@action\@anim@Minus a#1_spdDecr();% \else% \ifx\@anim@action\@anim@Reset a#1_spdReset();% \else% \ifx\@anim@action\@anim@Plus a#1_spdIncr();% \fi\fi\fi\fi\fi\fi\fi\fi\fi% }% }