% 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/11/30] \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% \MessageBreak% available. Therefore, MetaPost generated PS files% \MessageBreak% cannot be embedded using pdfTeX% }% \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}{% pdfTeX, version >= 1.20, required% }{% Install a newer version!% }% \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 \ifx\@undefined\pdfmdfivesum \def\pdfmdfivesum file #1{#1} \fi %creating and using global definitions \def\@anim@newkey#1#2{{\expandafter\xdef\csname#1\endcsname{#2}}} \def\@anim@getkeyval#1{% \expandafter\ifx\csname#1\endcsname\relax\else% \csname#1\endcsname% \fi% } %missing package error message \def\@anim@missing#1{% \PackageError{animate}{% Package `#1' has not been loaded yet% }{% Put the line\MessageBreak% `\protect\usepackage{#1}'\MessageBreak% to the preamble of your document!% }% } \newboolean{@anim@grxloaded} \setboolean{@anim@grxloaded}{false} \AtBeginDocument{% \@ifpackageloaded{graphicx}{% \setboolean{@anim@grxloaded}{true}% }{}% } %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 %tests whether file is known, if so it returns identifier of form xobj %otherwise `!' \def\@anim@fileknown#1#2{% #1 file name, #2 page No %identify file by md5sum \expandafter\ifx\csname file:\pdfmdfivesum file {#1}.#2\endcsname\relax!% \else\@anim@getkeyval{file:\pdfmdfivesum file {#1}.#2}\fi% } \def\@anim@makefileknown#1#2#3{% #1 file name, #2 page No, #3 Form XObj ID \@anim@newkey{file:\pdfmdfivesum file {#1}.#2}{#3}% } \ifpdf %helper macro that typesets graphics file into savebox \def\@anim@filebox#1#2{% #1 filename, #2 page No. for multipage files \ifx\@anim@gropts\@empty% \def\@anim@mps{.mps}% \ifx\@anim@ext\@anim@mps% \global\setbox\@anim@box=\hbox{\convertMPtoPDF{#1}{1}{1}}% \else% \pdfximage page #2 {#1}% \global\setbox\@anim@box=\hbox{\pdfrefximage\pdflastximage}% \fi% \else% \edef\@anim@curfile{*[page=#2\@anim@gropts]{#1}}% \global\setbox\@anim@box=\hbox{\expandafter\includegraphics\@anim@curfile}% \fi% } \else \def\@anim@filebox#1#2{% #1 filename, #2 ignored \ifx\@anim@gropts\@empty% \edef\@anim@curfile{*{#1}}% \else% \edef\@anim@curfile{*[\@anim@gropts]{#1}}% \fi% \global\setbox\@anim@box=\hbox{\expandafter\includegraphics\@anim@curfile}% } \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 pdf \ifthenelse{\equal{\@anim@fileknown{#3}{#4}}{!}}{% new file to be embedded \@anim@filebox{#3}{#4}% store file in a box \@anim@xinline{#1}{#2}{\@anim@box}{!}% delegate Form XObject creation \ifx\@anim@gropts\@empty\if@anim@multipdf\message{<#4>}\fi\fi% \@anim@makefileknown{#3}{#4}{\@anim@lastxform}% keep form xobject number }{% file known, re-use existing form xobject \ifnum#2=0 \@anim@filebox{#3}{#4}% for size determination of first frame \@anim@xinline{#1}{#2}{\@anim@box}{\@anim@fileknown{#3}{#4}}% \else% \@anim@xinline{#1}{#2}{}{\@anim@fileknown{#3}{#4}}% \fi% }% } \newboolean{@anim@timeline} %true if `timeline' option was set %creates Form XObject from box contents \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% \ifthenelse{\equal{#4}{!}}{% %put graphics into XObject \setbox\@anim@box=\hbox{% \raisebox{-\dp#3}[\@anim@animheight\p@][\@anim@animdepth\p@]{\box#3}% }% \immediate\pdfxform\@anim@box% \xdef\@anim@lastxform{\the\pdflastxform}% \if@anim@timeline% %keep a record of XObject number \@anim@newkey{img@#2}{\@anim@lastxform\space 0 R}% \else% \xdef\@anim@xobject{%XObject resource entry of container XObject \@anim@xobject\space/im#2\space\@anim@lastxform\space 0 R% }% \fi% }{% \if@anim@timeline% \@anim@newkey{img@#2}{#4\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}% %Properties entry for use in container XObject \xdef\@anim@properties{% \@anim@properties\space/oc#2\space\@anim@curocg% }% %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% \ifthenelse{\equal{#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}% \if@anim@timeline% \@anim@newkey{img@#2}{{@anim@frm@#1@#2}}% \else% \xdef\@anim@xobject{% XObject resource entry of container XObject \@anim@xobject\space/im#2\space {@anim@frm@#1@#2}% }% \fi% }{% \if@anim@timeline% \@anim@newkey{img@#2}{{#4}}% \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}% %Properties entry for use in container XObject \xdef\@anim@properties{% \@anim@properties\space/oc#2\space {@anim@ocg@#1@#2}% }% %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 \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% } \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% } \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 {% \if@anim@timeline\else/Properties <<\@anim@properties>>\fi /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 << \if@anim@timeline\else/Properties <<\@anim@properties>>\fi /XObject <<\@anim@xobject>> >> >> /PUT pdfmark }% } \fi %intermediate container XObject, for use with the timeline option, which %represents one animation frame and which contains all the transparencies %that compose the frame \ifpdf \def\@anim@makeframe#1#2{% #1:@anim@num, #2:@anim@curframe@zb \@anim@newocg{#1}{#2}% \setlength{\unitlength}{1pt}% \global\setbox\@anim@box=\hbox{% \pdfliteral{q}% \begin{picture}(\@anim@animwidth,\@anim@animtotalheight)% \end{picture}% \pdfliteral{Q\@anim@getkeyval{frmcontent@#2}}% }% \immediate\pdfxform attr {/OC\space\@anim@curocg} resources {% /XObject <<\@anim@getkeyval{frmxobject@#2}>>}\@anim@box% \xdef\@anim@xobject{\@anim@xobject\space /fr#2\space% \the\pdflastxform\space 0 R}% \xdef\@anim@content{\@anim@content\space q /fr#2\space Do Q}% } \else \def\@anim@makeframe#1#2{% \@anim@newocg{#1}{#2}% \special{ps: mark /_objdef {@anim@anmfrm@#1@#2} /type/stream /OBJ pdfmark mark {@anim@anmfrm@#1@#2} (\@anim@getkeyval{frmcontent@#2}) /PUT pdfmark mark {@anim@anmfrm@#1@#2} << /Type/XObject/Subtype/Form/FormType 1 /BBox [frame@llx frame@lly frame@urx frame@ury] /OC {@anim@ocg@#1@#2} /Resources <>>> >> /PUT pdfmark }% \xdef\@anim@xobject{\@anim@xobject\space /fr#2\space {@anim@anmfrm@#1@#2}}% \xdef\@anim@content{\@anim@content\space q /fr#2\space Do Q}% } \fi %create container XObjects for play & pause button faces \ifpdf \def\@anim@makeppcontainer#1#2#3{% #1: @anim@num, #2: Right or Left, % #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 savebox \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\p@}{% \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\p@ {% \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% }% } \newboolean{@anim@multipdf} % multipage PDF? \ifpdf %detects multipage PDF and corrects user supplied page range \def\@anim@checkmultipdf#1{% #1: file base name \IfFileExists{#1.pdf}{% \gdef\@anim@ext{.pdf}% \@anim@filebox{#1.pdf}{1}% \ifx\@anim@first\@empty% \@anim@curframe=\@ne% \else% \ifnum\@anim@first<0 \gdef\@anim@first{0}\fi% \@anim@curframe=\@anim@first% \advance\@anim@curframe by \@ne% because pdfximage pages are 1-based \ifnum\@anim@curframe>\pdflastximagepages \@anim@curframe=\pdflastximagepages% correct wrong user input \fi% \fi% \xdef\@anim@first{\the\@anim@curframe}% \ifx\@anim@last\@empty% \@anim@curframe=\pdflastximagepages% \else% \ifnum\@anim@last<0 \gdef\@anim@last{0}\fi% \@anim@curframe=\@anim@last% \advance\@anim@curframe by \@ne% \ifnum\@anim@curframe>\pdflastximagepages \@anim@curframe=\pdflastximagepages% \fi% \fi% \ifnum\@anim@first>\@anim@curframe \xdef\@anim@last{\@anim@first}% \xdef\@anim@first{\the\@anim@curframe}% \else% \xdef\@anim@last{\the\@anim@curframe}% \fi% \setboolean{@anim@multipdf}{true}% }{}% } \else \def\@anim@checkmultipdf#1{}% no-op in dvi mode \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@checkmultipdf{\@anim@base}%test for multipage pdf \@anim@curframe=\@anim@first% \@anim@curframe@zb=0% % \if@anim@draft% \if@anim@multipdf% %store file in a box \@anim@filebox{\@anim@base.pdf}{\@anim@first}% \else% %get file name extension \@anim@getext{\@anim@base\@anim@first}% \@anim@filebox{\@anim@base\@anim@first\@anim@ext}{1}% \fi% %draw draftbox according to dimensions of the first frame \@anim@draftbox{\@anim@box}% \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% \if@anim@multipdf% %embed graphics \@anim@ximage{\the\@anim@num}{\the\@anim@curframe@zb}{\@anim@base.pdf}{% \the\@anim@curframe}% \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% }{1}% \fi% \advance\@anim@curframe by \@anim@every% \advance\@anim@curframe@zb by \@ne% \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 \@ne% \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\p@ {% \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\p@% *\ratio{\@anim@boxwidth\p@}{\@anim@animwidth\p@}% }\xdef\@anim@animheight{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{% \@anim@animdepth\p@% *\ratio{\@anim@boxwidth\p@}{\@anim@animwidth\p@}% }\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\p@% *\ratio{\@anim@boxwidth\p@}{\@anim@animwidth\p@}% }% \setlength{\@anim@tmpdimb}{\@anim@tmpdima-\@anim@boxheight\p@}% \xdef\@anim@animdepth{\strip@pt\@anim@tmpdimb}% }{% \ifthenelse{% height missing \equal{\@anim@boxheight}{}\AND% \NOT\equal{\@anim@boxdepth}{}% }{% \setlength{\@anim@tmpdima}{% \@anim@animtotalheight\p@% *\ratio{\@anim@boxwidth\p@}{\@anim@animwidth\p@}% }% \setlength{\@anim@tmpdimb}{\@anim@tmpdima-\@anim@boxdepth\p@}% \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\p@% *\ratio{\@anim@animheight\p@+\@anim@animdepth\p@}{% \@anim@animtotalheight\p@}% }% \xdef\@anim@animwidth{\strip@pt\@anim@tmpdima}% }{}% }% %apply scaling factor \setlength{\@anim@tmpdima}{\@anim@animwidth\p@}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animwidth{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animheight\p@}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animheight{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animdepth\p@}% \setlength{\@anim@tmpdima}{\@anim@boxscale\@anim@tmpdima}% \xdef\@anim@animdepth{\strip@pt\@anim@tmpdima}% \setlength{\@anim@tmpdima}{\@anim@animheight\p@}% \addtolength{\@anim@tmpdima}{\@anim@animdepth\p@}% \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\p@ height \@anim@animheight\p@ depth \@anim@animdepth\p@ {% /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\p@ {% \vrule width 0pt height \@anim@animheight\p@ depth \@anim@animdepth\p@% \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\p@ {% \vrule width 0pt height \@anim@animheight\p@ depth \@anim@animdepth\p@% \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 \newcount\@anim@skipfram % counter for skipped frames %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% \global\@anim@skipfram=0% \@anim@beginframe% \ignorespaces% }{% \unskip% \@anim@endframe{\the\@anim@num}{\the\@anim@curframe@zb}% \global\advance\@anim@curframe@zb by \@ne% \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 \@ne% \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 \ifnum\@anim@skipfram=0 \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 \@ne% \fi% \@anim@beginframe% \ignorespaces% } \newcommand{\@anim@newframestar}[1][]{% starred variant for pausing animation \ifnum\@anim@skipfram=0 % #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}% \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 \@ne% \fi% \@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}% \ifnum\@anim@skipfram=0 \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% \fi% \global\advance\@anim@skipfram by \@ne% \ifnum\@anim@skipfram=\@anim@every \global\@anim@skipfram=0% \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 \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} \newcount\@anim@tmpcnt %scratch counter for different uses \newcount\@anim@curlayer %takes the number of the current layer being processed \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 and resource list of each frame \@anim@newkey{frmxobject@\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@curframe@zb=0% \gdef\@anim@maxlayer{0}% highest layer index %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}{}}{}{% %process input line \expandafter\@anim@parseline\@anim@inputline\@nil% %combine the layers of the current frame \@anim@curlayer=0% \loop\ifnum\@anim@curlayer>\@anim@maxlayer\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{% layercontent@\the\@anim@curframe@zb.\the\@anim@curlayer}{}% \advance\@anim@curlayer by \@ne% \repeat% %build frame xobject \@anim@makeframe{#1}{\the\@anim@curframe@zb}% %clean-up \edef\@anim@usedlist{\@anim@getkeyval{usedin@\the\@anim@curframe@zb}}% \expandafter\@anim@resetusedlist\@anim@usedlist,:\@nil% \@anim@newkey{frmxobject@\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% } %reads one line of timeline file and splits into its colon separated parts \def\@anim@parseline#1:#2:#3\@nil{% \if@anim@step\else% \ifthenelse{\equal{#1}{*}}{%first field is a star (pause frame) \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{#2}% %treat the second field (new frame rate) \ifx\@anim@nfps\@empty% no change of 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 field (list of layer specifications) \global\@anim@curlayer=0 \@anim@parsethird#3;:\@nil% } %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 \xdef\@anim@maxlayer{\the\@anim@curlayer}% \fi% \@anim@parsethird#2\@nil% }% } %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 \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=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 layer and update frame xobject resource list %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 %detect multiple inclusion of the same transparency in the %current frame \expandafter\ifx\csname used@#1@\the\@anim@tmpcnt\endcsname\relax% %append transparency to ressource list \@anim@newkey{frmxobject@\the\@anim@tmpcnt}{% \@anim@getkeyval{frmxobject@\the\@anim@tmpcnt}\space% /im#1\space\@anim@getkeyval{img@#1}% }% %mark current transparency as used within the current frame \@anim@newkey{used@#1@\the\@anim@tmpcnt}{}% %append it to the list of transparencies used in current frame \@anim@newkey{usedin@\the\@anim@tmpcnt}{% \@anim@getkeyval{usedin@\the\@anim@tmpcnt}#1,}% \else% \PackageWarning{animate}{% Transparency #1 multiply included in frame \the\@anim@tmpcnt.% \MessageBreak% File \jobname.tex% }% \ifx\@anim@warned\@undefined% \AtEndDocument{% \PackageWarningNoLine{animate}{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% \MessageBreak% @ In certain animation frames, transparencies were% \space\space @\MessageBreak% @ multiply included. This may considerably slow\space% \space\space\space\space @\MessageBreak% @ down animation speed. Revise the timeline file of\space @% \MessageBreak% @ the corresponding animations! See the transcript\space% \space @\MessageBreak% @ file \jobname.log\MessageBreak% @ for additional information!\space\space\space\space\space% \space\space\space\space\space\space\space\space\space\space% \space\space\space\space\space\space\space\space @\MessageBreak% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% }% }% \gdef\@anim@warned{}% \fi% \fi% \@anim@newkey{layercontent@\the\@anim@tmpcnt.\the\@anim@curlayer}{% \@anim@getkeyval{layercontent@\the\@anim@tmpcnt.\the\@anim@curlayer} q /im#1\space Do Q% }% \advance\@anim@tmpcnt by \@ne% \repeat% \fi% \fi% } %reset embedded transparency list \def\@anim@resetusedlist#1,#2\@nil{% \ifthenelse{\equal{#1}{}}{}{% \expandafter\global\expandafter\let\csname used@#1@\the\@anim@curframe@zb\endcsname\@undefined% }% \ifthenelse{\equal{#2}{:}}{% \@anim@newkey{usedin@\the\@anim@curframe@zb}{}% }{\@anim@resetusedlist#2\@nil}% } %get number of repetitions of frame \def\@anim@getrepetitions#1x:\@nil{% \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\@nil{% helper macro to get number of colour components and \xdef\@anim@colour{\@anim@colour\space #1}% to replace : by ` ' in the arg \ifthenelse{\equal{#2}{!}}{}{% \global\advance\@anim@tmpcnt by \@ne% \@anim@colours#2\@nil% }% } \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=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:!\@nil% \xdef\@anim@bgcolour{\@anim@colour}% \ifpdf% \ifnum\@anim@tmpcnt=\@ne \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=\@ne \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=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:!\@nil% \xdef\@anim@fgcolour{\@anim@colour}% \ifpdf% \ifthenelse{\the\@anim@tmpcnt=\@ne}{% \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=\@ne}{% \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}% } \define@key{anim@user}{every}{% embed every #1 frames \ifnum#1<\@ne\gdef\@anim@every{1}\else\gdef\@anim@every{#1}\fi% } \define@key{anim@user}{bb}{% \if@anim@grxloaded\xdef\@anim@gropts{\@anim@gropts, bb=#1}% \else\@anim@missing{graphicx}\fi% } \define@key{anim@user}{viewport}{% \if@anim@grxloaded\xdef\@anim@gropts{\@anim@gropts, viewport=#1}% \else\@anim@missing{graphicx}\fi% } \define@key{anim@user}{trim}{% \if@anim@grxloaded\xdef\@anim@gropts{\@anim@gropts, trim=#1}% \else\@anim@missing{graphicx}\fi% } %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}% \global\let\if@anim@controls=\if@anim@@controls% \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% \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}% \global\@anim@begin={}% \global\@anim@end={}% \gdef\@anim@every{1}% frames to be included \gdef\@anim@gropts{}% \setboolean{@anim@multipdf}{false}% } %package options \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}% \ifpdf% \ifnum\@anim@tmpcnt=\@ne \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=\@ne \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=\@ne% \gdef\@anim@colour{}% \@anim@colours#1:!\@nil% \xdef\@anim@@fgcolour{\@anim@colour}% \ifpdf% \ifthenelse{\the\@anim@tmpcnt=\@ne}{% \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=\@ne}{% \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(){% a#1.fr[a#1.idx].state=false;% try{% a#1.fr[--a#1.idx].state=true;% }catch(e){% ++a#1.idx;% \if@anim@palindrome% \if@anim@step a#1.actnEndLeft();% a#1.playsRight=true;% \else a#1.fr[a#1.idx].state=true;% if(a#1.isPlaying){a#1.isPaused=true;a#1.actnPlayRight();}% \fi% \else% \if@anim@step a#1.actnEndLeft();% \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();}% \else a#1.actnEndLeft();% \fi% \fi% \fi% }% \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% }% }