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