% 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, ...) % makes use of OCGs (Optional Content Groups, aka PDF Layers) % Supports LaTeX->dvips->ps2pdf or pdfLaTeX workflows. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{animate}[2007/09/17] \RequirePackage{keyval} \RequirePackage{ifthen} \RequirePackage{ifpdf} \RequirePackage{ifdraft} \RequirePackage{calc} \DeclareOption*{}\ProcessOptions*\relax %allow anything as option %(package options will be processed near end of this file) \ifpdf %load MP to PDF converter \ifx\convertMPtoPDF\@undefined% \InputIfFileExists{supp-pdf}{}{}% \ifx\convertMPtoPDF\@undefined% \PackageWarningNoLine{animate}{% File `supp-pdf.tex', which is part of ConTeXt, is not available.% \MessageBreak% Therefore, MetaPost generated PS files cannot be embedded.% }% \fi% \fi% \else %define `?pdfmark' operator as in file hdvips.def from package `hyperref' \AtBeginDvi{% \ifx\pdfmark\@undefined% \special{! systemdict /pdfmark known% {% userdict /?pdfmark systemdict /exec get put% }{% userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put% }% ifelse% }% \fi% } \fi% %testing for correct pdfTeX version \ifpdf \ifnum\pdftexversion<120 \PackageError{animate}{% pdfeTeX, version >= 1.20, required% }{% Install a newer version!% }% \fi \fi %creating and using global definitions \def\@anim@newkey#1#2{{\expandafter\xdef\csname#1\endcsname{#2}}} \def\@anim@getkeyval#1{\csname#1\endcsname} %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 OCProperties dict to Catalog \ifpdf \newcount\@anim@@ocgs \pdfobj reserveobjnum \@anim@@ocgs=\pdflastobj \newcount\@anim@@posterocgs \pdfobj reserveobjnum \@anim@@posterocgs=\pdflastobj \pdfcatalog{ /OCProperties << /OCGs \the\@anim@@ocgs\space 0 R /D <> >> } \def\@anim@ocgs{} \def\@anim@posterocgs{} \AtEndDocument{% \immediate\pdfobj useobjnum \@anim@@ocgs {% [\@anim@ocgs]% }% \immediate\pdfobj useobjnum \@anim@@posterocgs {% [\@anim@posterocgs]% }% }% \else \special{ps: % array which takes all ocgs (one per animation frame) mark /_objdef {@anim@ocgs} /type/array /OBJ pdfmark % array which takes ocgs shown by default (the poster frames) mark /_objdef {@anim@posterocgs} /type/array /OBJ pdfmark mark {Catalog} << /OCProperties << /OCGs {@anim@ocgs} /D <> >> >> /PUT pdfmark } \fi \newbox\@anim@box %stores animation frames \newdimen\@anim@tmpdima %length registers for occasional use \newdimen\@anim@tmpdimb \ifx\pdfmdfivesum\@undefined% %tests whether file is known, if so it returns identifier of form xobj %otherwise `!' \def\@anim@fileknown#1{% #1 filename %identify file by name \expandafter\ifx\csname file:#1\endcsname\relax!% \else\@anim@getkeyval{file:#1}\fi% } %helper macro that associates filename with identifier of xobject \def\@anim@makefileknown#1#2{% #1 file name, #2 obj identifier \@anim@newkey{file:#1}{#2}% } \else \def\@anim@fileknown#1{% #1 file name %identify file by md5sum \expandafter\ifx\csname file:\pdfmdfivesum file {#1}\endcsname\relax!% \else\@anim@getkeyval{file:\pdfmdfivesum file {#1}}\fi% }% \def\@anim@makefileknown#1#2{% \@anim@newkey{file:\pdfmdfivesum file {#1}}{#2}% } \fi \def\@anim@pt{pt} \ifpdf %helper macro that typesets graphics file into savebox \def\@anim@filebox#1{% #1 filename \def\@anim@mps{.mps}% \ifx\@anim@ext\@anim@mps% \global\setbox\@anim@box=\hbox{\convertMPtoPDF{#1}{1}{1}}% \else% \pdfximage{#1}% \global\setbox\@anim@box=\hbox{\pdfrefximage\pdflastximage}% \fi% } \else \def\@anim@filebox#1{% #1 filename \edef\@anim@curfile{{#1}}% \global\setbox\@anim@box=\hbox{\expandafter\includegraphics\@anim@curfile}% } \fi %create Form XObject from graphics file \def\@anim@ximage#1#2#3{%#1:@anim@num, #2:@anim@curframe@zb, #3:filename \ifthenelse{\equal{\@anim@fileknown{#3}}{!}}{% new file to be embedded \@anim@filebox{#3}% store file in a box \@anim@xinline{#1}{#2}{\@anim@box}{!}% delegate Form XObject creation \@anim@makefileknown{#3}{\@anim@lastxform}% keep form xobject number }{% file known, re-use existing form xobject \ifnum#2=0% \@anim@filebox{#3}% for size determination of first frame \@anim@xinline{#1}{#2}{\@anim@box}{\@anim@fileknown{#3}}% \else% \@anim@xinline{#1}{#2}{}{\@anim@fileknown{#3}}% \fi% }% } \newboolean{@anim@timeline} %true if `timeline' option was set %creates Form XObject from box contents and associates it with a newly %created OCG \ifpdf% %#1: @anim@num, #2:@anim@curframe@zb, #3: empty (`') or box number, %#4: `!' or form xobj identifier \def\@anim@xinline#1#2#3#4{% \ifnum#2=0% measuring the size of the box (first frame only) \xdef\@anim@animwidth{\strip@pt\wd#3}% \xdef\@anim@animheight{\strip@pt\ht#3}% \xdef\@anim@animdepth{\strip@pt\dp#3}% \setlength{\@anim@tmpdima}{\ht#3}% \addtolength{\@anim@tmpdima}{\dp#3}% \xdef\@anim@animtotalheight{\strip@pt\@anim@tmpdima}% \fi% \ifx #4!% %put graphics into XObject \setbox\@anim@box=\hbox{% \raisebox{-\dp#3}[\@anim@animheight\@anim@pt]% [\@anim@animdepth\@anim@pt]{\box#3}% }% \immediate\pdfxform\@anim@box% \xdef\@anim@lastxform{\the\pdflastxform}% \xdef\@anim@xobject{%XObject resource entry of container XObject \@anim@xobject\space/im#2\space\@anim@lastxform\space 0 R% }% \else% \xdef\@anim@xobject{\@anim@xobject\space/im#2\space #4\space 0 R}% \fi% \if@anim@timeline\else% \@anim@newocg{#1}{#2}%new ocg %compose content stream of container XObject \xdef\@anim@content{% \@anim@content\space /OC/oc#2\space BDC q /im#2\space Do Q EMC% }% \fi% } \else \def\@anim@xinline#1#2#3#4{% \ifnum#2=0% \xdef\@anim@animwidth{\strip@pt\wd#3}% \xdef\@anim@animheight{\strip@pt\ht#3}% \xdef\@anim@animdepth{\strip@pt\dp#3}% \setlength{\@anim@tmpdima}{\ht#3}% \addtolength{\@anim@tmpdima}{\dp#3}% \xdef\@anim@animtotalheight{\strip@pt\@anim@tmpdima}% \fi% \ifx #4!% \begingroup% \setlength{\unitlength}{1pt}% %mark BBox of the graphics \begin{picture}(0,0)% \put(0,-\@anim@animdepth){% \special{ps: currentpoint /frame@lly exch def /frame@llx exch def }% }% \put(\@anim@animwidth,\@anim@animheight){% \special{ps: currentpoint /frame@ury exch def /frame@urx exch def }% }% \end{picture}% \endgroup% %distill graphics into XObject \special{ps: gsave mark /_objdef {@anim@frm@#1@#2} /BBox [frame@llx frame@lly frame@urx frame@ury] /BP pdfmark {% isls{%landscape mode (powerdot, geometry /w landscape option) /frame@dxdy {% frame@urx frame@llx sub abs frame@ury frame@lly sub abs div% } bind def /frame@dydx {1 frame@dxdy div} bind def /frame@cx {frame@urx frame@llx add 2 div} bind def /frame@cy {frame@ury frame@lly add 2 div} bind def [% graphics needs to be rescaled for some reason ... frame@dxdy 0 0 frame@dydx 1 frame@dxdy sub frame@cx mul 1 frame@dydx sub frame@cy mul% ] concat %... rotated by 270 degrees ... [0 -1 1 0 frame@cx frame@cy sub frame@cx frame@cy add] concat %... and flipped around vertical axis [-1 0 0 1 frame@llx frame@urx add 0] concat% }{% flip around horizontal axis in portrait mode [1 0 0 -1 0 frame@lly frame@ury add] concat% }ifelse } ?pdfmark }% \begin{picture}(0,0)% \put(0,0){\box#3}% \end{picture}% \special{ps: mark /EP pdfmark grestore }% \xdef\@anim@lastxform{@anim@frm@#1@#2}% \xdef\@anim@xobject{% XObject resource entry of container XObject \@anim@xobject\space/im#2\space {@anim@frm@#1@#2}% }% \else% \xdef\@anim@xobject{% XObject resource entry of container XObject \@anim@xobject\space/im#2\space {#4}% }% \fi% \if@anim@timeline\else% \@anim@newocg{#1}{#2}% new ocg %compose content stream of container XObject \xdef\@anim@content{% \@anim@content\space /OC/oc#2\space BDC q /im#2\space Do Q EMC% }% \fi% } \fi %creates OCG and builds Properties entry for use in container XObject \ifpdf \def\@anim@newocg#1#2{%#1:@anim@num, #2:@anim@curframe@zb \immediate\pdfobj{<>}% new ocg \xdef\@anim@curocg{\the\pdflastobj\space 0 R}% %append to ocg array \xdef\@anim@ocgs{\@anim@ocgs\space\@anim@curocg}% %store ref to ocg if it's a poster \ifnum#2=0% \def\@anim@posterframe{first}% \else% \def\@anim@posterframe{last}% \fi% \ifx\@anim@poster\@anim@posterframe% \xdef\@anim@posterocg{\@anim@curocg}% \fi% %compose Properties entry for use in container XObject \xdef\@anim@properties{% \@anim@properties\space/oc#2\space\@anim@curocg% }% } \else \def\@anim@newocg#1#2{%#1:@anim@num, #2:@anim@curframe@zb \special{ps: mark /_objdef {@anim@ocg@#1@#2} /type/dict /OBJ pdfmark %new ocg mark {@anim@ocg@#1@#2} << /Type/OCG /Name (#1.#2) >> /PUT pdfmark mark {@anim@ocgs} {@anim@ocg@#1@#2} /APPEND pdfmark }% \ifnum#2=0% \def\@anim@posterframe{first}% \else% \def\@anim@posterframe{last}% \fi% \ifx\@anim@poster\@anim@posterframe% \xdef\@anim@posterocg{@anim@ocg@#1@#2}% \fi% \xdef\@anim@properties{% \@anim@properties\space/oc#2\space {@anim@ocg@#1@#2}% }% } \fi %create XObject which contains all frames of the sequence \ifpdf \def\@anim@makecontainer#1{% #1:@anim@num \setlength{\unitlength}{1pt}% \global\setbox\@anim@box=\hbox{% \pdfliteral{q}% \begin{picture}(\@anim@animwidth,\@anim@animtotalheight)% \end{picture}% \pdfliteral{Q\@anim@content}% }% \immediate\pdfxform resources {% /Properties <<\@anim@properties>> /XObject <<\@anim@xobject>> }\@anim@box% \xdef\@anim@container{\the\pdflastxform\space 0 R}% } \else \def\@anim@makecontainer#1{% \special{ps: mark /_objdef {@anim@xobj#1} /type/stream /OBJ pdfmark mark {@anim@xobj#1} (\@anim@content) /PUT pdfmark mark {@anim@xobj#1} << /Type/XObject/Subtype/Form/FormType 1 /BBox [frame@llx frame@lly frame@urx frame@ury] /Resources << /Properties <<\@anim@properties>> /XObject <<\@anim@xobject>> >> >> /PUT pdfmark }% } \fi %create container XObjects for play & pause button faces; \ifpdf \def\@anim@makeppcontainer#1#2#3{% #1: @anim@num, #2: Right or Left, %OCGs #3: index of existing button face colour combination \immediate\pdfobj{<>}% \edef\@anim@playocg{\the\pdflastobj\space 0 R}% \immediate\pdfobj{<< /Type/OCG /Name (#1.Pause#2)>>}% \edef\@anim@pauseocg{\the\pdflastobj\space 0 R}% %append to ocg array \xdef\@anim@ocgs{\@anim@ocgs\space\@anim@playocg\space\@anim@pauseocg}% %although not really necessary, append play button ocg to posterocg array \xdef\@anim@posterocgs{\@anim@posterocgs\space\@anim@playocg}% %new container XObject \immediate\pdfobj stream attr{% /Type/XObject/Subtype/Form/BBox [0 0 15 15]% /Resources <<% /Properties <>% /XObject <<% /im0 \@anim@getkeyval{btnPlay#2:#3} /im1 \@anim@getkeyval{btnPause#2:#3}% >>% >>% }{% /OC/oc0 BDC q /im0 Do Q EMC /OC/oc1 BDC q /im1 Do Q EMC% }% \@anim@newkey{btn#1.PlayPause#2}{\the\pdflastobj\space 0 R}% } \else \def\@anim@makeppcontainer#1#2#3{% \special{ps: %OCGs mark /_objdef {#1.Play#2} /type/dict /OBJ pdfmark mark {#1.Play#2} << /Type/OCG /Name (#1.Play#2) >> /PUT pdfmark mark /_objdef {#1.Pause#2} /type/dict /OBJ pdfmark mark {#1.Pause#2} << /Type/OCG /Name (#1.Pause#2) >> /PUT pdfmark %append to ocg array mark {@anim@ocgs} {#1.Play#2} /APPEND pdfmark mark {@anim@ocgs} {#1.Pause#2} /APPEND pdfmark %append play button ocg to posterocg array mark {@anim@posterocgs} {#1.Play#2} /APPEND pdfmark %new container XObject mark /_objdef {btn#1.PlayPause#2} /type/stream /OBJ pdfmark mark {btn#1.PlayPause#2} (% /OC/oc0 BDC q /im0 Do Q EMC /OC/oc1 BDC q /im1 Do Q EMC% ) /PUT pdfmark mark {btn#1.PlayPause#2} << /Type/XObject/Subtype/Form/FormType 1 /BBox [0 0 15 15] /Resources <<% /Properties <>% /XObject <<% /im0 {btnPlay#2:#3} /im1 {btnPause#2:#3}% >>% >>% >> /PUT pdfmark }% } \fi %create XObjects of all button faces \ifpdf %stroking commands \def\@anim@btnend{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 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{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 10 10 130 130 re S 10 w 50 40 m 100 75 l 50 110 l S } \def\@anim@btnplay{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 10 10 130 130 re S 10 w 50 40 m 50 110 l 100 75 l h S } \def\@anim@btnpause{% \@anim@bg\space 2.5 w 1 j \@anim@fg\space 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{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 10 10 130 130 re S 10 w 0 J 40 75 m 110 75 l S } \def\@anim@btnplus{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 10 10 130 130 re S 10 w 0 J 40 75 m 110 75 l 75 40 m 75 110 l S } \def\@anim@btnreset{% \@anim@bg\space 2.5 w 1 J 1 j \@anim@fg\space 10 10 130 130 re S 10 w 75 40 m 75 110 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 \@anim@btnend\space Q% }{#1}% \@anim@xbutton{EndRight}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnend\space Q% }{#1}% \@anim@xbutton{Minus}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnminus\space Q% }{#1}% \@anim@xbutton{PauseLeft}{% q -0.1 0 0 0.1 15 0 cm \@anim@btnpause\space Q% }{#1}% \@anim@xbutton{PauseRight}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnpause\space Q% }{#1}% \@anim@xbutton{PlayLeft}{% q -0.1 0 0 0.1 15 0 cm \@anim@btnplay\space Q% }{#1}% \@anim@xbutton{PlayRight}{% q 0.1 0 0 0.1 0 0 cm \@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 \@anim@btnreset\space Q% }{#1}% \@anim@xbutton{StepLeft}{% q -0.1 0 0 0.1 15 0 cm \@anim@btnstep\space Q% }{#1}% \@anim@xbutton{StepRight}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnstep\space Q% }{#1}% } %XObject creation \def\@anim@xbutton#1#2#3{% #1 name, #2 stroking commands, #3 @anim@num \immediate\pdfobj stream attr{% /Type/XObject/Subtype/Form/BBox [0 0 15 15]% }{#2}% \@anim@newkey{btn#1:#3}{\the\pdflastobj\space 0 R}% } \else \def\@anim@btnend{% \@anim@bg\space \@anim@fg\space 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{% \@anim@bg\space \@anim@fg\space 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{% \@anim@bg\space \@anim@fg\space 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{% \@anim@bg\space \@anim@fg\space 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{% \@anim@bg\space \@anim@fg\space 0.25 setlinewidth 1 setlinecap 1 setlinejoin 1 1 moveto 14 1 lineto 14 14 lineto 1 14 lineto closepath stroke 1.0 setlinewidth 0 setlinecap 4 7.5 moveto 11 7.5 lineto stroke } \def\@anim@btnplus{% \@anim@bg\space \@anim@fg\space 0.25 setlinewidth 1 setlinecap 1 setlinejoin 1 1 moveto 14 1 lineto 14 14 lineto 1 14 lineto closepath stroke 1.0 setlinewidth 0 setlinecap 4 7.5 moveto 11 7.5 lineto 7.5 4 moveto 7.5 11 lineto stroke } \def\@anim@btnreset{% \@anim@bg\space \@anim@fg\space 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#1{% #1: @anim@num \@anim@xbutton{EndLeft}{% [-1 0 0 1 15 0] concat \@anim@btnend% }{#1}% \@anim@xbutton{EndRight}{% \@anim@btnend% }{#1}% \@anim@xbutton{Minus}{% \@anim@btnminus% }{#1}% \@anim@xbutton{PauseLeft}{% [-1 0 0 1 15 0] concat \@anim@btnpause% }{#1}% \@anim@xbutton{PauseRight}{% \@anim@btnpause% }{#1}% \@anim@xbutton{PlayLeft}{% [-1 0 0 1 15 0] concat \@anim@btnplay% }{#1}% \@anim@xbutton{PlayRight}{% \@anim@btnplay% }{#1}% \@anim@xbutton{Plus}{% \@anim@btnplus% }{#1}% \@anim@xbutton{Reset}{% \@anim@btnreset% }{#1}% \@anim@xbutton{StepLeft}{% [-1 0 0 1 15 0] concat \@anim@btnstep% }{#1}% \@anim@xbutton{StepRight}{% \@anim@btnstep% }{#1}% } \def\@anim@xbutton#1#2#3{% #1: name; #2: stroking commands, #3 @anim@num \special{ps: gsave [1 0 0 1 0 0] setmatrix mark /_objdef {btn#1:#3} /BBox [0 0 15 15] /BP pdfmark {% %landscape mode (powerdot, geometry /w landscape option) isls{% [0 -1 1 0 0 15] concat % rotate by 270 degrees [-1 0 0 1 15 0] concat% flip around vertical axis }if #2 } ?pdfmark mark /EP pdfmark grestore }% } \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{.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}{% Neither 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 \def\@anim@getext#1{% \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}{% Neither 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?% }{}% }}}% }% \fi %counts embedded animations \newcount\@anim@num\@anim@num=0 %current frame \newcount\@anim@curframe \newcount\@anim@curframe@zb% zero based %draftbox from file \ifpdf \def\@anim@filedraftbox#1{% #1: filename %store file in a box \def\@anim@mps{.mps}% \ifx\@anim@ext\@anim@mps% \global\setbox\@anim@box=\hbox{\convertMPtoPDF{#1}{1}{1}}% \else% \pdfximage{#1}% \global\setbox\@anim@box=\hbox{\pdfrefximage\pdflastximage}% \fi% \@anim@draftbox{\@anim@box}% draw draft box with controls (if set) } \else \def\@anim@filedraftbox#1{% \edef\@anim@curfile{{#1}}% \global\setbox\@anim@box=\hbox{\expandafter\includegraphics\@anim@curfile}% \@anim@draftbox{\@anim@box}% } \fi %draftbox from savebox (lowlevel macro) \def\@anim@draftbox#1{% #1: box number %get size \xdef\@anim@animwidth{\strip@pt\wd#1}% \xdef\@anim@animheight{\strip@pt\ht#1}% \xdef\@anim@animdepth{\strip@pt\dp#1}% \setlength{\@anim@tmpdima}{\ht#1}% \addtolength{\@anim@tmpdima}{\dp#1}% \xdef\@anim@animtotalheight{\strip@pt\@anim@tmpdima}% \@anim@rescale% rescale box \setlength{\unitlength}{1pt}% \vtop{% draw boxes \offinterlineskip% \hbox{% \raisebox{-\@anim@animdepth\@anim@pt}{% \begin{picture}(\@anim@animwidth,\@anim@animtotalheight)% \put(0,0){\framebox(\@anim@animwidth,\@anim@animtotalheight){}}% \end{picture}% }% }% \if@anim@controls% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \vskip 0.1\@anim@tmpdima% \hbox to \@anim@animwidth\@anim@pt {% \hss% \setlength{\@anim@tmpdimb}{2\@anim@tmpdima}% \begin{picture}(\strip@pt\@anim@tmpdimb,\strip@pt\@anim@tmpdima)% \put(0,0){\line(1,0){\strip@pt\@anim@tmpdimb}}% \put(0,\strip@pt\@anim@tmpdima){% \line(1,0){\strip@pt\@anim@tmpdimb}% }% \put(0,0){\line(0,1){\strip@pt\@anim@tmpdima}}% \end{picture}% \if@anim@step\else% \begin{picture}(\strip@pt\@anim@tmpdimb,\strip@pt\@anim@tmpdima)% \put(0,0){\line(1,0){\strip@pt\@anim@tmpdimb}}% \put(0,\strip@pt\@anim@tmpdima){% \line(1,0){\strip@pt\@anim@tmpdimb}% }% \end{picture}% \fi% \begin{picture}(\strip@pt\@anim@tmpdimb,\strip@pt\@anim@tmpdima)% \put(0,0){\line(1,0){\strip@pt\@anim@tmpdimb}}% \put(0,\strip@pt\@anim@tmpdima){% \line(1,0){\strip@pt\@anim@tmpdimb}% }% \put(\strip@pt\@anim@tmpdimb,0){% \line(0,1){\strip@pt\@anim@tmpdima}% }% \end{picture}% \if@anim@step\else% \hskip 0.3\@anim@tmpdima% \setlength{\@anim@tmpdimb}{3\@anim@tmpdima}% \begin{picture}(\strip@pt\@anim@tmpdimb,\strip@pt\@anim@tmpdima)% \put(0,0){\line(0,1){\strip@pt\@anim@tmpdima}}% \put(0,0){\line(1,0){\strip@pt\@anim@tmpdimb}}% \put(0,\strip@pt\@anim@tmpdima){% \line(1,0){\strip@pt\@anim@tmpdimb}% }% \put(\strip@pt\@anim@tmpdimb,0){% \line(0,1){\strip@pt\@anim@tmpdima}% }% \end{picture}% \fi% \hss% }% \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][]{% \leavevmode% \begingroup% \ifpdf\else% \ifx\includegraphics\@undefined\@anim@missing{graphics}\fi% \fi% \@anim@reset% to default settings \setkeys{anim@user}{#1}% \def\@anim@base{#3}% \def\@anim@first{#4}% \def\@anim@last{#5}% % \@anim@curframe=\@anim@first% \@anim@curframe@zb=0% \if@anim@draft% %test for existence of all files of the sequence \loop\ifnum\@anim@curframe>\@anim@last\else% %get file name extension of current file (also tests for existence) \@anim@getext{% \@anim@base\@anim@pad{\@anim@first}{\the\@anim@curframe}% }% \advance\@anim@curframe by 1% \advance\@anim@curframe@zb by 1% \repeat% %draw draftbox according to dimensions of the first frame \@anim@filedraftbox{\@anim@base\@anim@first\@anim@ext}% \else% \if@anim@controls% %create button faces only once in the current colour combination \expandafter\ifx\csname btncol:\@anim@bgcolour:\@anim@fgcolour\endcsname\relax% \@anim@makebuttons{\the\@anim@num}% \@anim@newkey{btncol:\@anim@bgcolour:\@anim@fgcolour}{\the\@anim@num}% \fi% \if@anim@step\else% %combine Pause & Play button faces into one XObject \@anim@makeppcontainer{\the\@anim@num}{Right}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \@anim@makeppcontainer{\the\@anim@num}{Left}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \fi% \fi% \xdef\@anim@fps{#2}% current frame rate \xdef\@anim@nfps{#2}% % %read all frames of the sequence \loop\ifnum\@anim@curframe>\@anim@last\else% %get file name extension of current file \@anim@getext{% \@anim@base\@anim@pad{\@anim@first}{\the\@anim@curframe}% }% %embed graphics \@anim@ximage{\the\@anim@num}{\the\@anim@curframe@zb}{% \@anim@base\@anim@pad{\@anim@first}{\the\@anim@curframe}\@anim@ext% }% \advance\@anim@curframe by 1% \advance\@anim@curframe@zb by 1% \repeat% \xdef\@anim@frames{\the\@anim@curframe@zb}% total number %build timeline from optional timeline file \if@anim@timeline\@anim@buildtmln{\the\@anim@num}\fi% \@anim@makecontainer{\the\@anim@num}% create container XObject %insert animation widget & controls \@anim@insertwidgets{\the\@anim@num}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \fi% \global\advance\@anim@num by 1% \endgroup% }% %inserts animation and control button widgets \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\@anim@pt {% \hss% \@anim@buttonwidget{#1}{EndLeft}{EndLeft:#2}% \@anim@buttonwidget{#1}{StepLeft}{StepLeft:#2}% \if@anim@step\else% \@anim@buttonwidget{#1}{PlayPauseLeft}{#1.PlayPauseLeft}% \@anim@buttonwidget{#1}{PlayPauseRight}{#1.PlayPauseRight}% \fi% \@anim@buttonwidget{#1}{StepRight}{StepRight:#2}% \@anim@buttonwidget{#1}{EndRight}{EndRight:#2}% \if@anim@step\else% \hskip 0.3\@anim@tmpdima% \@anim@buttonwidget{#1}{Minus}{Minus:#2}% \@anim@buttonwidget{#1}{Reset}{Reset:#2}% \@anim@buttonwidget{#1}{Plus}{Plus:#2}% \fi% \hss% }% \fi% }% } %calculates widget dimensions from natural ones, taking resizing options %into account \def\@anim@rescale{% %rescale height & depth \ifthenelse{% \NOT\equal{\@anim@boxheight}{}\AND% \NOT\equal{\@anim@boxdepth}{}% }{% \xdef\@anim@animheight{\@anim@boxheight}% \xdef\@anim@animdepth{\@anim@boxdepth}% }{% \ifthenelse{\NOT\equal{\@anim@boxheight}{}}{% \xdef\@anim@animheight{\@anim@boxheight}% }{% \ifthenelse{\NOT\equal{\@anim@boxdepth}{}}{% \xdef\@anim@animdepth{\@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@animheight\@anim@pt% *\ratio{\@anim@boxwidth\@anim@pt}{\@anim@animwidth\@anim@pt}% }\xdef\@anim@animheight{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{% \@anim@animdepth\@anim@pt% *\ratio{\@anim@boxwidth\@anim@pt}{\@anim@animwidth\@anim@pt}% }\xdef\@anim@animdepth{\strip@pt\@anim@tmpdima}% }{}% }% }% }% \ifthenelse{\NOT\equal{\@anim@boxwidth}{}}{%rescale width \ifthenelse{% depth missing \NOT\equal{\@anim@boxheight}{}\AND% \equal{\@anim@boxdepth}{}% }{% \setlength{\@anim@tmpdima}{% \@anim@animtotalheight\@anim@pt% *\ratio{\@anim@boxwidth\@anim@pt}{\@anim@animwidth\@anim@pt}% }% \setlength{\@anim@tmpdimb}{\@anim@tmpdima-\@anim@boxheight\@anim@pt}% \xdef\@anim@animdepth{\strip@pt\@anim@tmpdimb}% }{% \ifthenelse{% height missing \equal{\@anim@boxheight}{}\AND% \NOT\equal{\@anim@boxdepth}{}% }{% \setlength{\@anim@tmpdima}{% \@anim@animtotalheight\@anim@pt% *\ratio{\@anim@boxwidth\@anim@pt}{\@anim@animwidth\@anim@pt}% }% \setlength{\@anim@tmpdimb}{\@anim@tmpdima-\@anim@boxdepth\@anim@pt}% \xdef\@anim@animheight{\strip@pt\@anim@tmpdimb}% }{}% }% \xdef\@anim@animwidth{\@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@animwidth\@anim@pt% *\ratio{% \@anim@animheight\@anim@pt+\@anim@animdepth\@anim@pt% }{\@anim@animtotalheight\@anim@pt}% }% \xdef\@anim@animwidth{\strip@pt\@anim@tmpdima}% }{}% }% %apply scaling factor \setlength{\@anim@tmpdima}{\@anim@animwidth\@anim@pt}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animwidth{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animheight\@anim@pt}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animheight{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animdepth\@anim@pt}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animdepth{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animheight\@anim@pt}% \addtolength{\@anim@tmpdima}{\@anim@animdepth\@anim@pt}% \xdef\@anim@animtotalheight{\strip@pt\@anim@tmpdima}% } %creates animation widget \ifpdf \def\@anim@animwidget#1{% \@anim@rescale% %create JavaScript objects \@anim@pojscript{#1}% to be executed on PO event \@anim@otherjscript{#1}% on other events in the AA dict %add poster to posterocg array \def\@anim@posterframe{none}% \ifx\@anim@poster\@anim@posterframe\else% \xdef\@anim@posterocgs{\@anim@posterocgs\space\@anim@posterocg}% \fi% \pdfannot width \@anim@animwidth\@anim@pt height \@anim@animheight\@anim@pt depth \@anim@animdepth\@anim@pt {% /Subtype/Widget% /F 4% allow printing /FT/Btn/Ff 65536% push button /BS <>% /H/N% /AP <>% /T (anm@#1)% /AA <<% bind JavaScripts to trigger events /PO <>% \@anim@otherjscriptkey% >>% }% \hbox to \@anim@animwidth\@anim@pt {% \vrule width 0pt height \@anim@animheight\@anim@pt depth \@anim@animdepth\@anim@pt% \hss% }% }% \else \def\@anim@animwidget#1{% \@anim@rescale% \setlength{\unitlength}{1pt}% %mark annotation rectangle \begin{picture}(0,0)% \put(0,-\@anim@animdepth){% \special{ps: currentpoint /wid@lly exch def /wid@llx exch def }% }% \put(\@anim@animwidth,\@anim@animheight){% \special{ps: currentpoint /wid@ury exch def /wid@urx exch def }% }% \end{picture}% \@anim@pojscript{#1}% \@anim@otherjscript{#1}% \def\@anim@posterframe{none}% \ifx\@anim@poster\@anim@posterframe\else% \special{ps: mark {@anim@posterocgs} {\@anim@posterocg} /APPEND pdfmark }% \fi \special{ps: mark /Rect [wid@llx wid@lly wid@urx wid@ury]% /Subtype/Widget% /F 4% /FT/Btn/Ff 65536% /BS <>% /H/N% /AP <>% /T (anm@#1)% /AA <<% /PO <>% \@anim@otherjscriptkey% >>% /ANN pdfmark }% \hbox to \@anim@animwidth\@anim@pt {% \vrule width 0pt height \@anim@animheight\@anim@pt depth \@anim@animdepth\@anim@pt% \hss% }% } \fi %creates control button widget \ifpdf \def\@anim@buttonwidget#1#2#3{%#1:@anim@num, #2:action, #3:button face XObject \@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 /BS <>% /H/I% /AP <>% /T (btn@#1@#2)% /A <>% }% \vrule width 0pt height \@anim@tmpdima depth 0pt% \hss% }% }% \else \def\@anim@buttonwidget#1#2#3{% \@anim@upjscript{#1}{#2}% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \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}% \special{ps: mark /Rect [wid@llx wid@lly wid@urx wid@ury] /Subtype/Widget /FT/Btn/Ff 65536 /BS <> /H/I /AP <>% /T (btn@#1@#2)% /A <>% /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} % `animateinline' environment \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 %user environment for animating inline graphics % #1: options % #2: frame rate (fps) \newenvironment{animateinline}[2][]{% \leavevmode% \begingroup% \setboolean{@anim@inside}{true}% \@anim@reset% to default settings \setkeys{anim@user}{#1}% \if@anim@draft\else% %create button faces if necessary \if@anim@controls% \expandafter\ifx\csname btncol:\@anim@bgcolour:\@anim@fgcolour\endcsname\relax% \@anim@makebuttons{\the\@anim@num}% \@anim@newkey{btncol:\@anim@bgcolour:\@anim@fgcolour}{\the\@anim@num}% \fi% \if@anim@step\else% \@anim@makeppcontainer{\the\@anim@num}{Right}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \@anim@makeppcontainer{\the\@anim@num}{Left}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \fi% \fi% \xdef\@anim@fps{#2}% \xdef\@anim@nfps{#2}% current frame rate (for use in \newframe) \fi% \global\@anim@curframe@zb=0% \@anim@beginframe% \ignorespaces% }{% \unskip% \@anim@endframe{\the\@anim@num}{\the\@anim@curframe@zb}% \global\advance\@anim@curframe@zb by 1% \if@anim@draft\else% \xdef\@anim@frames{\the\@anim@curframe@zb}% total number %build timeline from optional timeline file \if@anim@timeline\@anim@buildtmln{\the\@anim@num}\fi% \@anim@makecontainer{\the\@anim@num}% create container XObject %insert animation widget & controls \@anim@insertwidgets{\the\@anim@num}{% \@anim@getkeyval{btncol:\@anim@bgcolour:\@anim@fgcolour}}% \fi% \global\advance\@anim@num by 1% \setboolean{@anim@inside}{false}% \endgroup% } %usercommand for use within `animateinline' environment; %terminates the current frame and starts a new one \def\newframe{% \unskip% \if@anim@inside\else% \PackageError{animate}{% \protect\newframe\space cannot be used outside `animateinline'% \MessageBreak environment% }{}% \fi% \@anim@endframe{\the\@anim@num}{\the\@anim@curframe@zb}% \@ifstar\@anim@newframestar\@anim@newframe% } \newcommand{\@anim@newframe}[1][]{% #1: new frame rate \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% \edef\@anim@pfps{\@anim@nfps}% \edef\@anim@nfps{#1}% \ifx\@anim@nfps\@empty% \edef\@anim@nfps{\@anim@pfps}% \else% \ifnum\@anim@curframe@zb=0% \xdef\@anim@fps{#1}% \fi% %build JavaScript commands to fill the `nFpsAt' & `pFpsAt' arrays \xdef\@anim@nfpsat{% \@anim@nfpsat% a\the\@anim@num.nFpsAt[\the\@anim@curframe@zb]=Math.abs(#1);% }% \xdef\@anim@pfpsat{% \@anim@pfpsat% a\the\@anim@num.pFpsAt[\the\@anim@curframe@zb]=% Math.abs(\@anim@pfps);% }% \setboolean{@anim@chfps}{true}% change fps \fi% \fi% \fi% \fi% \global\advance\@anim@curframe@zb by 1% \@anim@beginframe% \ignorespaces% } \newcommand{\@anim@newframestar}[1][]{% starred variant for pauseing animation \if@anim@draft\else% #1: new frame rate \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}% \xdef\@anim@pfps{\@anim@nfps}% \xdef\@anim@nfps{#1}% \ifx\@anim@nfps\@empty% \xdef\@anim@nfps{\@anim@pfps}% \else% \ifnum\@anim@curframe@zb=0% \xdef\@anim@fps{#1}% \fi% %build JavaScript commands to fill the `nFpsAt' & `pFpsAt' arrays \xdef\@anim@nfpsat{% \@anim@nfpsat% a\the\@anim@num.nFpsAt[\the\@anim@curframe@zb]=Math.abs(#1);% }% \xdef\@anim@pfpsat{% \@anim@pfpsat% a\the\@anim@num.pFpsAt[\the\@anim@curframe@zb]=% Math.abs(\@anim@pfps);% }% \setboolean{@anim@chfps}{true}% change fps \fi% \fi% \fi% \fi% \global\advance\@anim@curframe@zb by 1% \@anim@beginframe% \ignorespaces% } %starts new frame \def\@anim@beginframe{% \begin{lrbox}{\@anim@box}% store graphics in a box \the\@anim@begin% } %terminates current frame \def\@anim@endframe#1#2{% \the\@anim@end% \end{lrbox}% \if@anim@draft\else\message{< a#1, fr#2}\fi% %determine size of graphics \ifnum #2=0% \xdef\@anim@animwidth{\strip@pt\wd\@anim@box}% \ifdim\wd\@anim@box=0pt% \PackageError{animate}{% Contents of first frame must not have zero width% }{% Possible reason: \protect\begin{animateinline}{...} immediately followed by \protect\newframe% }% \fi% \xdef\@anim@animheight{\strip@pt\ht\@anim@box}% \xdef\@anim@animdepth{\strip@pt\dp\@anim@box}% \ifdim\ht\@anim@box=0pt% \ifdim\dp\@anim@box=0pt% \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@draftbox{\@anim@box}\fi% \fi% %now create Form XObject of box contents \if@anim@draft\else\@anim@xinline{#1}{#2}{\@anim@box}{!}\message{>}\fi% } %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 (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% \ifnum10#1=1#2 \@anim@template{0#1}{#2}% \else% #1% \fi% \fi% }% %building timeline from timeline file \newread\@anim@@tmlnfile \newboolean{@anim@eof} \def\@anim@buildtmln#1{% #1:@anim@num \endlinechar=-1% suppress trailing space at input line end \global\@anim@curframe@zb=0% %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 of each frame (to be filled with refs to XObjects \@anim@newkey{@anim@content@\the\@anim@curframe@zb}{}% to be drawn) \global\advance\@anim@curframe@zb by 1% }% \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 transp \xdef\@anim@frames{\the\@anim@curframe@zb}% total number of anim positions \global\@anim@curframe@zb=0% %reopen timeline file and build timeline \openin\@anim@@tmlnfile=\@anim@tmlnfile% \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% \whiledo{\NOT\boolean{@anim@eof}}{% \ifthenelse{\equal{\@anim@inputline}{}}{}{% \expandafter\@anim@parseline\@anim@inputline;% %create OCG and compose Properties entry \@anim@newocg{#1}{\the\@anim@curframe@zb}% %compose content stream of container XObject \xdef\@anim@content{% \@anim@content\space% /OC/oc\the\@anim@curframe@zb\space% BDC\@anim@getkeyval{@anim@content@\the\@anim@curframe@zb} EMC% }% \global\advance\@anim@curframe@zb by 1% }% \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% } %reads one line of timeline file and splits into its colon separated parts \def\@anim@parseline#1:#2:#3;{% \if@anim@step\else% \ifx #1*% first column is a star (pause frame) \xdef\@anim@pauseat{% \@anim@pauseat% a\the\@anim@num.pauseAt[\the\@anim@curframe@zb]=1;% }% \setboolean{@anim@pauseframes}{true}% \fi% \xdef\@anim@pfps{\@anim@nfps}% \xdef\@anim@nfps{#2}% \ifx\@anim@nfps\@empty% second column contains a number (new frame rate) \xdef\@anim@nfps{\@anim@pfps}% \else% \ifnum\@anim@curframe@zb=0% \xdef\@anim@fps{#2}% \fi% %build JavaScript commands to fill the `nFpsAt' & `pFpsAt' arrays \xdef\@anim@nfpsat{% \@anim@nfpsat% a\the\@anim@num.nFpsAt[\the\@anim@curframe@zb]=Math.abs(#2);% }% \xdef\@anim@pfpsat{% \@anim@pfpsat% a\the\@anim@num.pFpsAt[\the\@anim@curframe@zb]=Math.abs(\@anim@pfps);% }% \setboolean{@anim@chfps}{true}% change fps \fi% \fi% %parse the third column \@anim@parsethird#3,:;% } %parses 3rd column of timeline file (comma separated list of transp. specs) \def\@anim@parsethird#1,#2;{% \def\@anim@firstarg{#1}% \ifx\@anim@firstarg\@empty\else% \@anim@process#1x:;% process one transparency spec \fi% \ifx #2:\else% \@anim@parsethird#2;% \fi% } \newcount\@anim@tmpcnt %scratch counter for different uses %process transparency spec, such as 123 or 456x78 or 9x0 \def\@anim@process#1x#2;{% %determine number of repetitions of current transparency \ifx #2:% \gdef\@anim@repeats{1}% \else% \@anim@processsecond#2;% \fi% \ifnum\@anim@repeats=0% 0= means: repeat until end of timeline \edef\@anim@repeatuntil{\@anim@frames}% \else% \@anim@tmpcnt=\@anim@curframe@zb% \advance\@anim@tmpcnt by \@anim@repeats% \ifnum\@anim@frames<\@anim@tmpcnt% \edef\@anim@repeatuntil{\@anim@frames}% \else% \edef\@anim@repeatuntil{\the\@anim@tmpcnt}% \fi% \fi% %build contents of animation frames according to transparency specifications \ifnum\@anim@transp<#1\else% ignore non-existing transparencies \ifnum\@anim@transp=#1\else% \@anim@tmpcnt=\@anim@curframe@zb% \loop\ifnum\@anim@repeatuntil>\@anim@tmpcnt% \@anim@newkey{@anim@content@\the\@anim@tmpcnt}{% \@anim@getkeyval{@anim@content@\the\@anim@tmpcnt} q /im#1\space Do Q% }% \advance\@anim@tmpcnt by 1% \repeat% \fi% \fi% } %get number of repetitions of frame \def\@anim@processsecond#1x:;{% \gdef\@anim@repeats{#1}% } %command options %setting the widget size \define@key{anim@user}{width}{% \setlength{\@anim@tmpdima}{#1}% \xdef\@anim@boxwidth{\strip@pt\@anim@tmpdima}% } \define@key{anim@user}{height}{% \setlength{\@anim@tmpdima}{#1}% \xdef\@anim@boxheight{\strip@pt\@anim@tmpdima}% } \define@key{anim@user}{depth}{% \setlength{\@anim@tmpdima}{#1}% \xdef\@anim@boxdepth{\strip@pt\@anim@tmpdima}% } \define@key{anim@user}{scale}{% \gdef\@anim@boxscale{#1}% } \define@key{anim@user}{buttonsize}{% \gdef\@anim@btnsize{#1}% } \def\@anim@colours#1:#2;{% helper macro to get number of colour components and \xdef\@anim@colour{\@anim@colour\space #1}% to replace : by ` ' in the arg \ifx #2!\else% \global\advance\@anim@tmpcnt by 1% \@anim@colours#2;% \fi% } \ifpdf %background frame of buttons \def\@anim@@@bg{% 0 j 0 0 150 150 re f% } \else \def\@anim@@@bg{% 0 setlinejoin 0 0 moveto 15 0 lineto 15 15 lineto 0 15 lineto closepath fill% } \fi \define@key{anim@user}{buttonbg}{%background colour of buttons \global\@anim@tmpcnt=1% \gdef\@anim@colour{}% \@anim@colours#1:!;% \xdef\@anim@bgcolour{\@anim@colour}% \ifpdf% \ifnum\@anim@tmpcnt=1 \xdef\@anim@bg{\@anim@colour\space g\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=3 \xdef\@anim@bg{\@anim@colour\space rg\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=4 \xdef\@anim@bg{\@anim@colour\space k\space\@anim@@@bg}% \fi% \fi% \fi% \else% \ifnum\@anim@tmpcnt=1 \xdef\@anim@bg{\@anim@colour\space setgray\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=3 \xdef\@anim@bg{\@anim@colour\space setrgbcolor\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=4 \xdef\@anim@bg{\@anim@colour\space setcmykcolor\space\@anim@@@bg}% \fi% \fi% \fi% \fi% } \define@key{anim@user}{buttonfg}{%stroking colour of buttons \global\@anim@tmpcnt=1% \gdef\@anim@colour{}% \@anim@colours#1:!;% \xdef\@anim@fgcolour{\@anim@colour}% \ifpdf% \ifthenelse{\the\@anim@tmpcnt=1}{% \xdef\@anim@fg{\@anim@colour\space G}% \xdef\@anim@@@fg{\@anim@colour\space g}% }{% \ifthenelse{\the\@anim@tmpcnt=3}{% \xdef\@anim@fg{\@anim@colour\space RG}% \xdef\@anim@@@fg{\@anim@colour\space rg}% }{% \ifthenelse{\the\@anim@tmpcnt=4}{% \xdef\@anim@fg{\@anim@colour\space K}% \xdef\@anim@@@fg{\@anim@colour\space k}% }{}% }% }% \else% \ifthenelse{\the\@anim@tmpcnt=1}{% \xdef\@anim@fg{\@anim@colour\space setgray}% }{% \ifthenelse{\the\@anim@tmpcnt=3}{% \xdef\@anim@fg{\@anim@colour\space setrgbcolor}% }{% \ifthenelse{\the\@anim@tmpcnt=4}{% \xdef\@anim@fg{\@anim@colour\space setcmykcolor}% }{}% }% }% \fi% } \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}% } %default frame to be shown if animation is not activated \define@key{anim@user}{poster}[first]{% | none | last \ifthenelse{% correct wrong input to `none' \equal{#1}{first}\OR% \equal{#1}{last}% }{% \gdef\@anim@poster{#1}% }{% \gdef\@anim@poster{none}% }% } \newboolean{@anim@step} \setboolean{@anim@step}{false} \define@key{anim@user}{step}[true]{% \setboolean{@anim@step}{#1}% } \newboolean{@anim@draft} \setboolean{@anim@draft}{false} \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}{timeline}{% \IfFileExists{#1}{% \gdef\@anim@tmlnfile{#1}% \setboolean{@anim@timeline}{true}% }{% \PackageError{animate}{timeline file `#1' cannot be opened for reading% }{% Make sure file `#1' exists and is readable!% }% }% } \newtoks\@anim@begin \define@key{anim@user}{begin}{% \@anim@begin{#1}% } \newtoks\@anim@end \define@key{anim@user}{end}{% \@anim@end{#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@fg{\@anim@@fg}% \ifpdf\xdef\@anim@@@fg{\@anim@@@@fg}\fi% \xdef\@anim@bgcolour{\@anim@@bgcolour}% default button colours \xdef\@anim@fgcolour{\@anim@@fgcolour}% \xdef\@anim@btnsize{\@anim@@btnsize}% \xdef\@anim@poster{\@anim@@poster}% \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% \let\if@anim@step=\if@anim@@step% \let\if@anim@draft=\if@anim@@draft% \gdef\@anim@posterocg{}% \gdef\@anim@properties{}% \gdef\@anim@xobject{}% \gdef\@anim@content{}% \setboolean{@anim@pauseframes}{false}% \gdef\@anim@pauseat{}% \setboolean{@anim@chfps}{false}% \gdef\@anim@nfpsat{}% \gdef\@anim@pfpsat{}% \gdef\@anim@tmlnfile{}% \setboolean{@anim@timeline}{false}% \@anim@begin={}% \@anim@end={}% } %package options \def\@anim@@bg{} \def\@anim@@bgcolour{} \define@key{anim@pkg}{buttonbg}{%background colour of buttons \global\@anim@tmpcnt=1% \gdef\@anim@colour{}% \@anim@colours#1:!;% \xdef\@anim@@bgcolour{\@anim@colour}% \ifpdf% \ifnum\@anim@tmpcnt=1 \xdef\@anim@@bg{\@anim@colour\space g\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=3 \xdef\@anim@@bg{\@anim@colour\space rg\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=4 \xdef\@anim@@bg{\@anim@colour\space k\space\@anim@@@bg}% \fi% \fi% \fi% \else% \ifnum\@anim@tmpcnt=1 \xdef\@anim@@bg{\@anim@colour\space setgray\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=3 \xdef\@anim@@bg{\@anim@colour\space setrgbcolor\space\@anim@@@bg}% \else% \ifnum\@anim@tmpcnt=4 \xdef\@anim@@bg{\@anim@colour\space setcmykcolor\space\@anim@@@bg}% \fi% \fi% \fi% \fi% } \ifpdf\def\@anim@@fg{0 G}\def\@anim@@@@fg{0 g}\else\def\@anim@@fg{0 setgray}\fi \def\@anim@@fgcolour{} \define@key{anim@pkg}{buttonfg}{%stroking colour of buttons \global\@anim@tmpcnt=1% \gdef\@anim@colour{}% \@anim@colours#1:!;% \xdef\@anim@@fgcolour{\@anim@colour}% \ifpdf% \ifthenelse{\the\@anim@tmpcnt=1}{% \xdef\@anim@@fg{\@anim@colour\space G}% \xdef\@anim@@@@fg{\@anim@colour\space g}% }{% \ifthenelse{\the\@anim@tmpcnt=3}{% \xdef\@anim@@fg{\@anim@colour\space RG}% \xdef\@anim@@@@fg{\@anim@colour\space rg}% }{% \ifthenelse{\the\@anim@tmpcnt=4}{% \xdef\@anim@@fg{\@anim@colour\space K}% \xdef\@anim@@@@fg{\@anim@colour\space k}% }{}% }% }% \else% \ifthenelse{\the\@anim@tmpcnt=1}{% \xdef\@anim@@fg{\@anim@colour\space setgray}% }{% \ifthenelse{\the\@anim@tmpcnt=3}{% \xdef\@anim@@fg{\@anim@colour\space setrgbcolor}% }{% \ifthenelse{\the\@anim@tmpcnt=4}{% \xdef\@anim@@fg{\@anim@colour\space setcmykcolor}% }{}% }% }% \fi% } \def\@anim@@btnsize{1.44em}% \define@key{anim@pkg}{buttonsize}{% \gdef\@anim@@btnsize{#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}% } \gdef\@anim@@poster{first}% \define@key{anim@pkg}{poster}[first]{% \ifthenelse{% \equal{#1}{first}\OR% \equal{#1}{last}% }{% \gdef\@anim@@poster{#1}% }{% \gdef\@anim@@poster{none}% }% } \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}% }% } %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 event \ifpdf \def\@anim@pojscript#1{% \immediate\pdfobj stream {\@anim@@pojscript{#1}}% \xdef\@anim@pojscriptobj{\the\pdflastobj\space 0 R}% } \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@posterlast{last}% helper macro \def\@anim@@pojscript#1{% #1: @anim@num % console.show();% % console.clear();% if(typeof(a#1)=='undefined'){% initialize animation a#1=new Object();% %takes references to frame ocgs belonging to the current animation a#1.fr=new Array();% %takes references to control button face ocgs \if@anim@controls a#1.btn=new Array();\fi %get array of ocgs of current page var ocg=this.getOCGs(this.pageNum);% for(var i=0;i=0&&% a#1.nFpsAt[a#1.idx]!=a#1.fpsDeflt% ){% a#1.fpsDeflt=a#1.nFpsAt[a#1.idx];% a#1.dtDeflt=1000/(1e-6+a#1.fpsDeflt);% a#1.dt=a#1.dtDeflt;% if(a#1.isPlaying){a#1.isPaused=true;a#1.actnPlayRight();}% }% \fi% \if@anim@pauseframes if(a#1.isPlaying&&a#1.pauseAt[a#1.idx]){a#1.actnPause();}% \fi% \fi% };% a#1.actnPrev=function(){% var curIdx=a#1.idx;% \if@anim@palindrome if(a#1.idx==0){% \if@anim@step a#1.playsRight=true;% \else if(a#1.isPlaying){a#1.isPaused=true;a#1.actnPlayRight();}% \fi% }else{% a#1.idx--;% }% \else if(a#1.idx==0){% \if@anim@step\else% \if@anim@loop if(a#1.isPlaying){% \if@anim@chfps a#1.fpsDeflt=Math.abs(\@anim@nfps);% a#1.dtDeflt=1000/(1e-6+a#1.fpsDeflt);% a#1.dt=a#1.dtDeflt;% \fi a#1.actnPlayLeft();% }% \else a#1.actnEndLeft();% \fi% \fi% }else{% a#1.idx--;% }% \fi a#1.fr[curIdx].state=false;% a#1.fr[a#1.idx].state=true;% \if@anim@step\else% \if@anim@chfps if(% a#1.pFpsAt[a#1.idx]>=0&&% a#1.pFpsAt[a#1.idx]!=a#1.fpsDeflt% ){% a#1.fpsDeflt=a#1.pFpsAt[a#1.idx];% a#1.dtDeflt=1000/(1e-6+a#1.fpsDeflt);% a#1.dt=a#1.dtDeflt;% if(a#1.isPlaying){a#1.isPaused=true;a#1.actnPlayLeft();}% }% \fi% \if@anim@pauseframes if(a#1.isPlaying&&a#1.pauseAt[a#1.idx]){a#1.actnPause();}% \fi% \fi% };% \if@anim@step\else 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.btn['PauseLeft'].state=false;% a#1.btn['PlayLeft'].state=true;% a#1.btn['PauseRight'].state=false;% a#1.btn['PlayRight'].state=true;% \fi% };% a#1.actnPlayRight=function(){% try{app.clearInterval(a#1_int);}catch(e){}% if(!a#1.isPaused){a#1.actnEndLeft();}% a#1.playsRight=true;% a#1.isPlaying=true;% a#1.isPaused=false;% \if@anim@controls a#1.btn['PauseLeft'].state=true;% a#1.btn['PlayLeft'].state=false;% a#1.btn['PauseRight'].state=true;% a#1.btn['PlayRight'].state=false;% \fi a#1_int=app.setInterval('a#1.actnNext()',a#1.dt);% };% a#1.actnPlayLeft=function(){% try{app.clearInterval(a#1_int);}catch(e){}% if(!a#1.isPaused){a#1.actnEndRight();}% a#1.playsRight=false;% a#1.isPlaying=true;% a#1.isPaused=false;% \if@anim@controls a#1.btn['PauseLeft'].state=true;% a#1.btn['PlayLeft'].state=false;% a#1.btn['PauseRight'].state=true;% a#1.btn['PlayRight'].state=false;% \fi 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 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.actnReset=function(){% reset to default speed a#1.dt=a#1.dtDeflt;% 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% \fi% }% \if@anim@step\else% \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% \fi% } %other trigger events in the anim widget's AA dictionary \def\@anim@otherjscript#1{% \def\@anim@posterframe{last}% \xdef\@anim@otherjscriptkey{% /PC <>% \if@anim@step\else% /D <>% \fi% /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.actnEndLeft();% \else% \ifx\@anim@action\@anim@StepLeft% \if@anim@step a#1.actnPrev();% \else if(!a#1.isPlaying){a#1.isPaused=true;a#1.actnPrev();}% \fi% \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@anim@step a#1.actnNext();% \else if(!a#1.isPlaying){a#1.isPaused=true;a#1.actnNext();}% \fi% \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% }% }