JezK
Edit File: animate.sty
% Copyright 2007--today Alexander Grahn % This material is subject to the LaTeX Project Public License. See % http://mirrors.ctan.org/macros/latex/base/lppl.txt % for the details of that license. % Package for creating portable, JavaScript driven animations from sets of % graphics files or inline graphics (e. g. LaTeX-picture, PSTricks, % pgf/TikZ, ...) % Supports LaTeX->dvips->ps2pdf, (Xe)LaTeX->(x)dvipdfmx, LuaLaTeX, % pdfLaTeX and LaTeX->dvisvgm workflows. \NeedsTeXFormat{LaTeX2e}[2022-06-01] \def\@anim@version{2022/09/15} \ProvidesPackage{animate} [\@anim@version\space PDF & SVG animations from files and inline graphics] \RequirePackage{ifthen} \RequirePackage{iftex} \RequirePackage{ifdraft} \RequirePackage{calc} %driver options (the only package options we process immediately) \newboolean{@anim@dvips} \newboolean{@anim@dvipdfmx} \newboolean{@anim@dvisvgm} \newboolean{@anim@xetex} \newboolean{@anim@export}%exporting animation frames \ExplSyntaxOn \DeclareKeys[anim@pkg]{ pdftex.code:n = {}, pdftex.value_forbidden:n = true, luatex.code:n = {}, luatex.value_forbidden:n = true, xetex.code:n = {}, xetex.value_forbidden:n = true, dvips.code:n = {}, dvips.value_forbidden:n = true, dvipdfmx.code:n = { \PassOptionsToPackage{dvipdfmx}{pdfbase} \PassOptionsToPackage{dvipdfmx}{ocgbase} \PassOptionsToPackage{dvipdfmx}{graphics} }, dvipdfmx.value_forbidden:n = true, dvisvgm.code:n = { \PassOptionsToPackage{dvisvgm}{pdfbase} \PassOptionsToPackage{dvisvgm}{graphics} }, dvisvgm.value_forbidden:n = true, export.legacy_if_gset:n = @anim@export, export.default:n = true, } \ExplSyntaxOff \DeclareUnknownKeyHandler[anim@pkg]{} \ProcessKeyOptions[anim@pkg] % remaining package options to be processed near end of this file \RequirePackage{pdfbase} \@ifpackagelater{pdfbase}{2022/08/04}{}{ \PackageError{animate}{% Support package `pdfbase.sty' too old.% }{% Please install an up to date version of `pdfbase.sty'.\MessageBreak% Aborting.% }% } \ifpdf\else \setboolean{@anim@dvips}{true}% default dvi mode \fi \ExplSyntaxOn \bool_if:NT\g_pbs_dvipdfmx_bool{ \setboolean{@anim@dvipdfmx}{true} \setboolean{@anim@dvips}{false} } \bool_if:NT\g_pbs_dvisvgm_bool{ \setboolean{@anim@dvisvgm}{true} \setboolean{@anim@dvips}{false} } \sys_if_engine_xetex:T{ \bool_if:NT\g_pbs_dvipdfmx_bool{\setboolean{@anim@xetex}{true}} \setboolean{@anim@dvips}{false} } \ExplSyntaxOff \RequirePackage{graphics}%\scalebox, \resizebox, \rotatebox \RequirePackage{zref-abspage} \newboolean{@anim@insideexport} \newenvironment{anim@export}{% \global\@anim@insideexporttrue% }{% \global\@anim@insideexportfalse% } % get number of pages in file given as #1 (file basename); #2 extension; % store result into macro given as #3 \ifpdf %pdflatex/lualatex \def\@anim@getpagecount#1#2#3{% \pdfximage page 1 {#1.#2}\xdef#3{\the\pdflastximagepages}% } \else \if@anim@xetex \def\@anim@getpagecount#1#2#3{% \xdef#3{\the\numexpr\XeTeXpdfpagecount "#1.#2"\relax}% } \else \if@anim@dvips \def\@anim@getpagecount#1#2#3{\gdef#3{1}}% \else %dvipdfmx, dvisvgm \def\@anim@getpagecount#1#2#3{{% \global\let#3\@undefined% \def\%##1: ##2:{% \expandafter\edef\csname ##1\endcsname{##2}% \global\let#3\Pages% }% \endlinechar`\:% `:' appended to every line read \IfFileExists{#1.xbb}{% %read from xbb file {\catcode`\:=12\catcode`\%=0\sbox0{\input{#1.xbb}}}% \ifdefined#3\else% \PackageError{animate}{% Cannot read number of pages from file\MessageBreak% -------------------------------------\MessageBreak% #1.xbb\MessageBreak% -------------------------------------\MessageBreak% This file seems to be invalid and should be deleted% }{}% \fi% }{% %read from command pipe (`extractbb') %firstly, check whether reading from pipe is allowed \immediate\closein\@inputcheck% \immediate\openin\@inputcheck="|extractbb -h"\relax% \ifeof\@inputcheck% \immediate\closein\@inputcheck% \PackageError{animate}{% Cannot determine number of pages in file\MessageBreak% ----------------------------------------\MessageBreak% #1.#2\MessageBreak% ----------------------------------------\MessageBreak% Try --shell-escape option (--enable-pipes in MiKTeX),% \MessageBreak or run\MessageBreak% \space\space extractbb #1.#2\MessageBreak% on the command line to provide a valid `xbb' file% }{}% \else% \immediate\closein\@inputcheck% {\catcode`\:=12\catcode`\%=0\sbox0{\@@input "|extractbb -O #1.#2"}}% \fi% }% }} \fi \fi \fi \if@anim@dvisvgm \setboolean{@anim@export}{false} \fi \if@anim@export \@ifclassloaded{standalone}{}{ \PackageError{animate}{% Option `export' requires the `standalone' document class.\MessageBreak% Replace current document class with `standalone'% }{% Put the line\MessageBreak% `\protect\documentclass{standalone}'\MessageBreak% at the beginning of the document preamble.% }% }% \standaloneenv{anim@export} \fi %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % low level PDF/SVG operations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ExplSyntaxOn \let\@anim@literal\pbs_literal:nn \def\@anim@xform#1#2#3#4#5{ \pbs_pdfxform:nnnnn{#1}{#2}{#3}{#4}{#5} \xdef\@anim@lastxform{\pbs_pdflastxform:} } \let\@anim@refxform\pbs_pdfrefxform:n \def\@anim@annot#1#2#3#4{ \pbs_pdfannot:nnnn{#1}{#2}{#3}{#4} } \let\@anim@fpeval\fp_eval:n %hashing object references of embedded files to avoid multiple inclusion \let\@anim@pdfmdfivesum\file_mdfive_hash:n \ExplSyntaxOff \if@anim@dvisvgm \def\@anim@updatebbox#1#2#3{\special{dvisvgm:bbox #1 #2 #3 transform}} %approach similar to OCGs, that is, putting the frame content in an svg group, % <g id='...'>...</g>, whose visibility is then manipulated by JavaScript \def\@anim@newocg#1#2{\xdef\@anim@curocg{id='_#1.#2' class='ocg'}} \def\ocgbase@add@to@off@list#1{% \xdef\@anim@curocg{\@anim@curocg\space visibility='hidden'}% } \def\ocgbase@oc@bdc#1{\special{dvisvgm:raw <g #1>}} \def\ocgbase@oc@emc{\special{dvisvgm:raw </g>}} \else \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@widget#1#2#3#4{ \pbs_pdfannot:nnnn{#1}{#2}{#3}{#4} \pbs_appendtofields:n{\pbs_pdflastann:} } \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}% } \fi %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %creating and using global definitions \def\@anim@newkey#1#2{{\expandafter\xdef\csname#1\endcsname{#2}}} \def\@anim@getkeyval#1{\ifcsname#1\endcsname\csname#1\endcsname\fi} \def\@animate@rerunwarn{% \ifcsname @anim@rerunwarned\endcsname\else% \gdef\@anim@rerunwarned{}% \PackageWarningNoLine{animate}{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak @ Rerun to get internal references right! @\MessageBreak @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% \fi% } %macro for writing global defs to external *.aux file \def\@anim@keytoaux#1#2{% \immediate\write\@mainaux{\string\@anim@newkey{#1}{#2}}% \ifthenelse{\equal{\@anim@getkeyval{#1}}{#2}}{}{% \AtEndDocument{\@animate@rerunwarn}}% } \AtBeginDocument{% \immediate\write\@mainaux{\string\providecommand\string\@anim@newkey[2]{}}% } %missing package error message \newcommand{\@anim@missing}[2][]{% \ifthenelse{\equal{#1}{}}{% \def\@anim@pkgopt{}% }{% \def\@anim@pkgopt{[#1]}% }% \PackageError{animate}{% Package `#2' required. Put the line\MessageBreak% `\protect\usepackage\@anim@pkgopt{#2}'\MessageBreak% to the preamble of your document% }{}% } \newboolean{@anim@grxloaded} \setboolean{@anim@grxloaded}{false} \AtBeginDocument{% \@ifpackageloaded{graphicx}{\setboolean{@anim@grxloaded}{true}}{}% \gdef\@anim@lscape{}% \gdef\@anim@@lscape{:ls}% \ifdefined\landscape% \g@addto@macro{\landscape}{\gdef\@anim@lscape{:ls}}% \g@addto@macro{\endlandscape}{\gdef\@anim@lscape{}}% \fi% } % true if any of `autoplay' or `autoresume' options is set \newboolean{@anim@autoplayorresume} % true if any of `controls' or `palindrome' or `label' options is set \newboolean{@anim@timeline} %true if `timeline' option is set \newboolean{@anim@multipage} % multipage document? \newboolean{@anim@nomouse} % animation widget to react on mouse events? \newbox\@anim@box %stores animation frames \newbox\@anim@measbox % for measuring purposes \newdimen\@anim@tmpdima %length registers for occasional use \newdimen\@anim@tmpdimb \def\@anim@firstofthree#1#2#3{#1} \def\@anim@secndofthree#1#2#3{#2} \def\@anim@thirdofthree#1#2#3{#3} %macros for recalling saved nat. dimensions \def\@anim@xformnatwd#1{\expandafter\@anim@firstofthree#1} \def\@anim@xformnatht#1{\expandafter\@anim@secndofthree#1} \def\@anim@xformnatdp#1{\expandafter\@anim@thirdofthree#1} %helper macro that typesets graphics file into savebox \if@anim@dvips \def\@anim@filebox#1#2#3#4{% dvips: no multi-page support \edef\@anim@curfile{[#3]{#1}}% \setbox#4=\hbox{% \expandafter\includegraphics\@anim@curfile}% } \else %pdfTeX, LuaTeX, dvipdfmx, xetex, dvisvgm \def\@anim@filebox#1#2#3#4{% \edef\@anim@curfile{[#3,page=#2]{#1}}% \setbox#4=\hbox{% \expandafter\includegraphics\@anim@curfile}% } \fi \def\@anim@checkboxsize#1#2{% #1: box number, #2: file \ifdim\wd#1=\z@% \PackageError{animate}{% Graphics to be used for first frame% \MessageBreak must not have zero width% }{% Check content of file #2% }% \fi% \ifdim\ht#1=\z@\ifdim\dp#1=\z@% \PackageError{animate}{% Graphics to be used for first frame% \MessageBreak must not have zero height% }{% Check content of file #2% }% \fi\fi% } %create Form XObject from graphics file \def\@anim@ximage#1#2#3#4#5{%#1:@anim@num, #2:@anim@curframe@zb, #3:filename, % #4: page number of multipage file, #5 graphicx inclusion options % fingerprint "<file chksum>.<page>.<graphicx opts>.<current document page>" % of external graphics to prevent re-embedding \edef\@anim@fingerprint{% \@anim@pdfmdfivesum{#3}.#4.#5% \if@anim@dvisvgm.\@anim@abspage\fi% }% \edef\@anim@curxform{\@anim@getkeyval{xform:\@anim@fingerprint}}% \ifthenelse{\equal{\@anim@curxform}{}}{% % new file \@anim@filebox{#3}{#4}{#5}{\@anim@box}% store file in a box \edef\@anim@natdims{{\the\wd\@anim@box}{\the\ht\@anim@box}{\the\dp\@anim@box}}% \@anim@xinline{#1}{#2}{\@anim@box}{newfile}% Form XObject creation \@anim@newkey{natdims:\@anim@lastxform}{\@anim@natdims}% \@anim@newkey{scaleddims:\@anim@lastxform}{% scaled dimensions {\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}% }% \@anim@newkey{xform:\@anim@fingerprint}{\@anim@lastxform}% }{% file known, re-using existing xform \edef\@anim@curndims{\@anim@getkeyval{scaleddims:\@anim@curxform}}% \setbox\@anim@box=\hbox to \@anim@xformnatwd{\@anim@curndims}{% \vrule width \z@ height \@anim@xformnatht{\@anim@curndims} depth \@anim@xformnatdp{\@anim@curndims}% \@anim@refxform{\@anim@curxform}% \hss% }% \@anim@xinline{#1}{#2}{\@anim@box}{\@anim@curxform}% }% } %creates Form XObject from box contents \def\@anim@xinline#1#2#3#4{% #1 anim num, #2 frame num, #3 box num, #4 status ( \edef\@anim@curwd{\the\wd#3}% `newfile', xform ref of known file or `inline') \edef\@anim@curht{\the\ht#3}% \edef\@anim@curdp{\the\dp#3}% % measure 0th frame, to determine final animation widget dims \ifnum#2=\z@\relax% \ifthenelse{\equal{#4}{newfile}\OR\equal{#4}{inline}}{% \setbox\@anim@measbox=\hbox to \wd#3{% \vrule width \z@ height \ht#3 depth \dp#3\hss}% }{% known file \edef\@anim@curndims{\@anim@getkeyval{natdims:#4}}% \setbox\@anim@measbox=\hbox to \@anim@xformnatwd{\@anim@curndims}{% \vrule width \z@ height \@anim@xformnatht{\@anim@curndims} depth \@anim@xformnatdp{\@anim@curndims}% \hss% }% }% \@anim@scale{\@anim@measbox}% \if@anim@dvisvgm% for clipping purposes \@anim@keytoaux{a#1.wdbp}{\strip@pt\dimexpr0.996264\dimexpr\@anim@animwidth}% \@anim@keytoaux{a#1.htbp}{\strip@pt\dimexpr0.996264\dimexpr\@anim@animheight}% \@anim@keytoaux{a#1.thtbp}{\strip@pt\dimexpr0.996264\dimexpr\@anim@animtotalheight}% \fi% \fi% \def\@anim@needresize{0}% % test if content dimensions differ from those of the final widget \ifdim\@anim@curwd=\@anim@animwidth\else\def\@anim@needresize{1}\fi% \ifdim\@anim@curht=\@anim@animheight\else\def\@anim@needresize{1}\fi% \ifdim\@anim@curdp=\@anim@animdepth\else\def\@anim@needresize{1}\fi% % resize content to final dimensions, if necessary \ifnum\@anim@needresize>\z@\relax% \setbox#3=\hbox{\resizebox{\@anim@animwidth}{\@anim@animheight}{\box#3}}% \fi% \ifthenelse{\equal{#4}{newfile}\OR\equal{#4}{inline}}{% \@anim@xform{1}{1}{}{}{#3}% %keep a record of XObject number \@anim@newkey{img@#2}{\@anim@lastxform}% }{% %known file \ifnum\@anim@needresize>\z@% \@anim@xform{0}{1}{}{}{#3}% \@anim@newkey{img@#2}{\@anim@lastxform}% \else% \@anim@newkey{img@#2}{#4}% \fi% }% \message{<a#1,fr#2>}% } \def\@anim@refxformlist#1,#2\@nil{% \ifthenelse{\equal{#1}{}}{}{% \if@anim@dvips% \@anim@refxform{{#1}}% \else% \@anim@refxform{#1}% \fi% }% \ifthenelse{\equal{#2}{}}{}{\@anim@refxformlist#2\@nil}% } % this counts the length of a clist <item a>,<item b>,<item b>,..., (note the % trailing comma) \def\@anim@countxformlist#1{% \expandafter\@anim@@countxformlist\expandafter0\expandafter:#1,\@nil% } \def\@anim@@countxformlist#1:#2,#3\@nil{% \ifx\relax#2\relax% \the\numexpr#1% \else% \ifx\relax#3\relax% \the\numexpr#1% \else% \expandafter\@anim@@countxformlist\the\numexpr #1+1:#3\@nil% \fi% \fi% } \def\@anim@zaptrailingcommafromxref#1,\@nil{\if@anim@dvips{#1}\else#1\fi}% % inserts one animation frame into the output acc. to \ifcase\@anim@method % as a non-interactive Widget annotation (0 or 1) or as an xform (2) that is % referenced in the page content (and tagged as OCG or for multipage PDF export) % args: #1 animation num, #2 frame number, #3 comma-separated list of xform % refs (transparencies) \def\@anim@makeframe#1#2#3{% \edef\@anim@arg{#3}% \setboolean{@anim@singleref}{false}\def\@anim@framexform{}% % count number of xforms in the frame content; a single xform can be referenced % at once, while a transparency list (multiple, overlayed xforms) must be boxed % and nested in an additional xform \ifnum\@anim@countxformlist{\@anim@arg}=\@ne% \setboolean{@anim@singleref}{true}% \edef\@anim@framexform{\expandafter\@anim@zaptrailingcommafromxref\@anim@arg\@nil}% \fi% % however, this isn't possible on landscape pages with \@anim@method==0|1 % because frame content needs to be rotated by 90 deg counterclockwise \ifnum\@anim@method>\@ne\else\ifx\@anim@lscape\@anim@@lscape% \setboolean{@anim@singleref}{false}\def\@anim@framexform{}% \fi\fi% % ... nor if the animation is to be exported to multipage PDF \if@anim@export% \setboolean{@anim@singleref}{false}\def\@anim@framexform{}% \fi% % ... also, for method=ocg, we prefer packing content in an xform, as it allows % higher frame rates \ifnum\@anim@method=\tw@\if@anim@dvisvgm\else% \setboolean{@anim@singleref}{false}\def\@anim@framexform{}% \fi\fi% \if@anim@singleref\else% % put frame content in a box if necessary \setbox\@anim@box=\hbox to \@anim@animwidth{% \vrule width \z@ height \@anim@animheight depth \@anim@animdepth% \expandafter\@anim@refxformlist\@anim@arg,\@nil% \hss% }% % rotate content on lscape pages \ifnum\@anim@method>\@ne\else\ifx\@anim@lscape\@anim@@lscape% \setbox\@anim@box=\hbox{\rotatebox{90}{\box\@anim@box}}% \fi\fi% \fi% \ifcase\@anim@method% icon based \if@anim@singleref\else% \@anim@xform{0}{1}{}{}{\@anim@box}% \let\@anim@framexform\@anim@lastxform% \fi% %initial visibility \ifnum\@anim@poster>\@anim@mtwo\relax% insert poster frame \ifnum#2=\@anim@poster\relax% \let\@anim@posterap\@anim@framexform% \else% \ifnum\@anim@poster=\@anim@mone\relax% use last frame as poster \let\@anim@posterap\@anim@framexform% \fi% \fi% \fi% %insert (invisible) widget with current frame as appearance \@anim@widget{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% /F 2% /FT/Btn/Ff 65537% /BS <</W 0>>% /AP <</N \@anim@framexform>>% /MK <</TP 1/I \@anim@framexform% /IF<</S/A/FB true>>>>% /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 \if@anim@singleref\else% \@anim@xform{0}{1}{}{}{\@anim@box}% \let\@anim@framexform\@anim@lastxform% \fi% \@anim@widget{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% \@anim@annotflag% /FT/Btn/Ff 65537% /BS <</W 0>>% /AP <</N \@anim@framexform>>% /MK <</TP 1/I \@anim@framexform% /IF<</S/A/FB true>>>>% /T (#1.#2)% }% \or% ocg-based (abused for dvisvgm backend as well as for % multipage PDF export) \if@anim@export% \if@anim@insideexport\else\anim@export\fi% \box\@anim@box% \endanim@export% \else% \@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% %frame insertion \if@anim@dvisvgm% \if@anim@singleref\else% \@anim@xform{0}{1}{}{}{\@anim@box}% \let\@anim@framexform\@anim@lastxform% \fi% % `marked content' method for dvisvgm \ocgbase@oc@bdc{\@anim@curocg}% \@anim@refxform{\@anim@framexform}% \ocgbase@oc@emc% \else% % /OC method for PDF output, higher frame rates than % with marked content (BDC/EMC) \@anim@xform{0}{1}{}{/OC \@anim@curocg}{\@anim@box}% \@anim@refxform{\@anim@lastxform}% \fi% \fi% \fi% } \newboolean{@anim@singleref} %create XObjects of all button faces \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 %dvips .OR. dvisvgm %stroking commands \def\@anim@btnend{% 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 bgfill grestore \fi \@anim@fg\space 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{% 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 bgfill grestore \fi \@anim@fg\space stroke % 1 setlinewidth 5.5 4.7 moveto 9.6 7.5 lineto 5.5 10.3 lineto stroke } \def\@anim@btnplay{% 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 bgfill grestore \fi \@anim@fg\space 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{% 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 bgfill grestore \fi \@anim@fg\space stroke % 0 setlinecap 2 setlinewidth 2.2 4 moveto 2.2 11 lineto stroke } \def\@anim@btnminus{% 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 bgfill grestore \fi \@anim@fg\space stroke % 1.0 setlinewidth 0 setlinecap 4.7 7.5 moveto 10.3 7.5 lineto stroke } \def\@anim@btnplus{% 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 bgfill grestore \fi \@anim@fg\space 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@btnresetbg{% Reset-button background for dvisvgm 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 \@anim@bg\space fill } \def\@anim@btnreset{% 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\if@anim@dvisvgm\else gsave \@anim@bg\space bgfill grestore \fi\fi \@anim@fg\space 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@makebutton#1#2{% #1: name ; #2:current colour, alpha, ... \edef\@anim@arg{#1}% \ifx\@anim@EndLeft\@anim@arg% \@anim@xbutton{EndLeft}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% [-1 0 0 1 15 0] concat \@anim@btnend}{#2}% \fi% \ifx\@anim@EndRight\@anim@arg% \@anim@xbutton{EndRight}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% \@anim@btnend}{#2}% \fi% \ifx\@anim@Minus\@anim@arg% \@anim@xbutton{Minus}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% \@anim@btnminus}{#2}% \fi% \ifx\@anim@PauseLeft\@anim@arg% \@anim@xbutton{PauseLeft}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% [-1 0 0 1 15 0] concat \@anim@btnpause}{#2}% \fi% \ifx\@anim@PauseRight\@anim@arg% \@anim@xbutton{PauseRight}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% \@anim@btnpause}{#2}% \fi% \ifx\@anim@PlayLeft\@anim@arg% \@anim@xbutton{PlayLeft}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% [-1 0 0 1 15 0] concat \@anim@btnplay}{#2}% \fi% \ifx\@anim@PlayRight\@anim@arg% \@anim@xbutton{PlayRight}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% \@anim@btnplay}{#2}% \fi% \ifx\@anim@Plus\@anim@arg% \@anim@xbutton{Plus}{\@anim@btnplus}{#2}% \fi% \ifx\@anim@Reset\@anim@arg% \if@anim@dvisvgm% Reset btn has filled foreground parts. In dvisvgm, for % filling and setting transparency correctly, BG and FG are treated % separately. \ifcsname btn#1:#2\endcsname\else% \ifx\empty\@anim@bg\empty\else% \@anim@xbutton{ResetBG}{\@anim@btnresetbg}{#2}% \fi% \begingroup% \def\@anim@alpha{}% \@anim@xbutton{ResetFG}{\@anim@btnreset}{#2}% \endgroup% \ifx\empty\@anim@bg\empty\else% \setbox\@anim@box=\hbox to \@anim@btnsize {% \vbox to \@anim@btnsize {\vss% \@anim@refxform{\@anim@getkeyval{btnResetBG:#2}}% \@anim@refxform{\@anim@lastxform}% }\hss% }% \@anim@xform{0}{1}{}{}{\@anim@box}% \fi% \@anim@newkey{btn#1:#2}{\@anim@lastxform}% \fi% \else% \@anim@xbutton{Reset}{% \ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi% \@anim@btnreset}{#2}% \fi% \fi% \ifx\@anim@StepLeft\@anim@arg% \@anim@xbutton{StepLeft}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% [-1 0 0 1 15 0] concat \@anim@btnstep}{#2}% \fi% \ifx\@anim@StepRight\@anim@arg% \@anim@xbutton{StepRight}{% \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% \@anim@btnstep}{#2}% \fi% } \def\@anim@xbutton#1#2#3{% #1: name; #2: stroking commands, % only create if button face doesn't exist yet \ifcsname btn#1:#3\endcsname\else% #3: current colour+alpha+ ... combination \setbox\@anim@box=\hbox to 15bp {\vbox to 15bp {\vss% \@anim@literal{}{% save \ifx\empty\@anim@alpha\empty% /bgfill {fill} bind def \else\if@anim@dvisvgm /bgfill {fill} bind def \else% /bgfill {% /.setfillconstantalpha where {% pop gsave \@anim@alpha\space .setfillconstantalpha fill 1 .setfillconstantalpha newpath fill grestore newpath% }{% /.setopacityalpha where {% pop gsave \@anim@alpha\space .setopacityalpha fill 1 .setopacityalpha newpath fill grestore newpath% }{% %Distiller gsave mark /ca \@anim@alpha\space/SetTransparency pdfmark fill mark /ca 1.0 /SetTransparency pdfmark newpath fill grestore newpath% } ifelse% } ifelse% } bind def \fi\fi% #2 restore% }% }\hss}% \if@anim@dvisvgm% \setbox\@anim@box=\hbox{% \resizebox*{!}{\@anim@btnsize}{\box\@anim@box}}% \fi% %distill box into XObject \@anim@xform{0}{1}{}{% \ifx\empty\@anim@alpha\empty\else\if@anim@dvisvgm% fill-opacity='\@anim@alpha'% \fi\fi% }{\@anim@box}% \@anim@newkey{btn#1:#3}{\@anim@lastxform}% \fi% } \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 \ifx\empty\@anim@alpha\empty\else/R2 gs \fi 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@makebutton#1#2{% #1: name ; #2: current colour, alpha, ... \edef\@anim@arg{#1}% \ifx\@anim@EndLeft\@anim@arg% \@anim@xbutton{EndLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnend\space Q% }{#2}% \fi% \ifx\@anim@EndRight\@anim@arg% \@anim@xbutton{EndRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnend\space Q% }{#2}% \fi% \ifx\@anim@Minus\@anim@arg% \@anim@xbutton{Minus}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnminus\space Q% }{#2}% \fi% \ifx\@anim@PauseLeft\@anim@arg% \@anim@xbutton{PauseLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnpause\space Q% }{#2}% \fi% \ifx\@anim@PauseRight\@anim@arg% \@anim@xbutton{PauseRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnpause\space Q% }{#2}% \fi% \ifx\@anim@PlayLeft\@anim@arg% \@anim@xbutton{PlayLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnplay\space Q% }{#2}% \fi% \ifx\@anim@PlayRight\@anim@arg% \@anim@xbutton{PlayRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnplay\space Q% }{#2}% \fi% \ifx\@anim@Plus\@anim@arg% \@anim@xbutton{Plus}{% q 0.1 0 0 0.1 0 0 cm \@anim@btnplus\space Q% }{#2}% \fi% \ifx\@anim@Reset\@anim@arg% \@anim@xbutton{Reset}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnreset\space Q% }{#2}% \fi% \ifx\@anim@StepLeft\@anim@arg% \@anim@xbutton{StepLeft}{% q -0.1 0 0 0.1 15 0 cm \ifx\@anim@lscape\@anim@@lscape 0 -1 -1 0 150 150 cm \fi% \@anim@btnstep\space Q% }{#2}% \fi% \ifx\@anim@StepRight\@anim@arg% \@anim@xbutton{StepRight}{% q 0.1 0 0 0.1 0 0 cm \ifx\@anim@lscape\@anim@@lscape 0 1 -1 0 150 0 cm \fi% \@anim@btnstep\space Q% }{#2}% \fi% } %XObject creation \def\@anim@xbutton#1#2#3{% #1 name, #2 stroking commands, #3 @anim@num \ifcsname btn#1:#3\endcsname\else% only create if button face doesn't% exist yet \edef\@anim@arg{#1}% \@anim@streamobj{% /Type/XObject/Subtype/Form/BBox [0 0 15 15]% \ifx\empty\@anim@alpha\empty\else% /Resources <<% /ExtGState <<% /R1 <</Type/ExtGState/ca \@anim@alpha>>% \ifx\@anim@Reset\@anim@arg% /R2 <</Type/ExtGState/ca 1.0>>% \fi% >>% >>% \fi% }{\ifx\empty\@anim@alpha\empty\else/R1 gs\fi\space #2}% \@anim@newkey{btn#1:#3}{\@anim@lastobj}% \fi% } \fi %determines file type of the sequence \def\zap@finalspace#1 \@nil{\unquote@name{#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{.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.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 \if@anim@dvisvgm \def\@anim@getpath#1#2{% \ifx\@empty#2\@empty% \gdef\@anim@ext{.pdf}% we start with `pdf' \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.eps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.ps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.mps}% \IfFileExists{#1\@anim@ext}{}{% \gdef\@anim@ext{.svg}% \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}{}{% \PackageError{animate}{% None of the files\MessageBreak% `#1.pdf',\MessageBreak% `#1.eps',\MessageBreak% `#1.ps',\MessageBreak% `#1.mps',\MessageBreak% `#1.svg',\MessageBreak% `#1.png',\MessageBreak% `#1.jpg',\MessageBreak% `#1.jpeg' or\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 \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{\z@}{\@anim@animtotalheight}\hskip\@anim@animwidth% }% }}% \if@anim@controls% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \setlength{\@anim@tmpdimb}{\z@}% \vskip 0.1\@anim@tmpdima% \hbox to \@anim@animwidth {% \if@anim@ctrlleft\hspace{\@anim@ctrlsindent}\fi% \ifnum\if@anim@ctrlright\@ne\else% \if@anim@ctrlcentre\@ne\else\z@\fi\fi=\@ne\hss\fi% \setboolean{@anim@controls@firstgrp}{false}% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@play% \setboolean{@anim@controls@firstgrp}{true}% \addtolength{\@anim@tmpdimb}{2\@anim@tmpdima}% \fi% \if@anim@controls@firstgrp% \frame{\phantom{\rule{\@anim@tmpdimb}{\@anim@tmpdima}}}% \fi% \if@anim@controls@speed% \if@anim@controls@firstgrp\hskip 0.3\@anim@tmpdima\fi% \frame{\phantom{\rule{3\@anim@tmpdima}{\@anim@tmpdima}}}% \fi% \ifnum\if@anim@ctrlleft\@ne\else% \if@anim@ctrlcentre\@ne\else\z@\fi\fi=\@ne\hss\fi% \if@anim@ctrlright\hspace{\@anim@ctrlsindent}\fi% }% \fi% }% \endgroup% } %detects multipage PDF and corrects user supplied page range \def\@anim@checkmultipage#1#2{% no multi-page support in dvips \setboolean{@anim@multipage}{false}}% \if@anim@dvips\else \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}% }{}% \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}% \filename@parse{\@anim@pathtofile}% \@anim@getpagecount{\filename@area\filename@base}{\filename@ext}{% \@anim@lastpage% }% \ifdefined\@anim@lastpage\else% double check multipage support \setboolean{@anim@multipage}{false}% \fi% \fi% \if@anim@multipage% %we need it zero-based \edef\@anim@lastpage{\the\numexpr\@anim@lastpage-\@ne\relax}% \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% \global\let\@anim@first\@anim@lastpage% \fi% \fi% \ifx\@anim@last\@empty% \global\let\@anim@last\@anim@lastpage% \else% \ifnum\@anim@last<\z@\relax\gdef\@anim@last{0}\fi% \ifnum\@anim@last>\@anim@lastpage\relax% \global\let\@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% }% \fi% %environment for setting LTR typesetting direction \def\@anim@beginLTR{% \ifdefined\textdir% LuaTeX \begingroup% \edef\@anim@curTxtDir{\the\textdir}% \textdir TLT\relax% \else% e-TeX based engines \ifnum\TeXXeTstate>\z@\beginL\fi% \fi% } \def\@anim@endLTR{% \ifdefined\textdir% \endgroup% \else% \ifnum\TeXXeTstate>\z@\endL\fi% \fi% } %user command for embedding animation sequence % #1: options % #2: frame rate (fps) % #3: basename of graphics file sequence (without frame number and extension) % #4: first frame (integer) % #5: last frame (integer) \newcommand{\animategraphics}[5][]{% \@anim@endsanitize% \if@anim@export\else\leavevmode\fi% \if@anim@grxloaded\else% \if@anim@dvipdfmx\if@anim@xetex% \@anim@missing{graphicx}\else% \@anim@missing[dvipdfmx]{graphicx}\fi% \else% \@anim@missing{graphicx}% \fi% \fi% \@anim@reset% to default settings \if@anim@dvisvgm% \special{dvisvgm:raw <!-- animation by LaTeX-package `animate', https://ctan.org/tex-archive/macros/latex/contrib/animate, v. \@anim@version\space-->% }% \fi% \begingroup% \@anim@beginLTR% \ifcsname Ginput@path\endcsname% make use of graphic[xs] search path \let\input@path\Ginput@path% \fi% \SetKeys[anim@user]{#1}% %store current abs. page num in macro \@anim@abspage \if@anim@dvisvgm\if@anim@draft\else% \zref@labelbyprops{anim@abspage\the\@anim@num}{abspage}% \zref@def@extractdefault{\@anim@abspage}{% anim@abspage\the\@anim@num}{abspage}{-1}% \fi\fi% \ifx\empty\@anim@bg\empty\xdef\@anim@alpha{}\fi% \xdef\@anim@btnsize{\the\dimexpr\@anim@btnsize\relax}% %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% \ifx\@anim@bb\@empty\else\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi\@anim@bb}\fi% \ifx\@anim@viewport\@empty\else\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi\@anim@viewport}\fi% \ifx\@anim@trim\@empty\else\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi\@anim@trim}\fi% \ifx\@anim@angle\@empty\else\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi\@anim@angle}\fi% \if@anim@hiresbb\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi hiresbb}\fi% \if@anim@interpolate\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi interpolate}\fi% \ifx\@anim@pagebox\@empty\else\xdef\@anim@gropts{\@anim@gropts% \ifx\@anim@gropts\@empty\else,\fi\@anim@pagebox}\fi% \ifthenelse{\boolean{@anim@autoplay}\OR\boolean{@anim@autoresume}}{% \setboolean{@anim@autoplayorresume}{true}% }{}% \ifthenelse{\NOT\boolean{@anim@controls}\AND\boolean{@anim@step}}{% \setboolean{@anim@loop}{true}% }{}% \if@anim@step% %for stepping animations, ignore any `controls' settings except \setboolean{@anim@controls@play}{false}% `step' and `stop' \setboolean{@anim@controls@speed}{false}% \setboolean{@anim@controls}{false}% \if@anim@controls@stop\setboolean{@anim@controls}{true}\fi% \if@anim@controls@step\setboolean{@anim@controls}{true}\fi% \fi% \edef\@anim@base{#3}% \edef\@anim@first{#4}% \edef\@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{>}% \let\@anim@numtemplate\@anim@first% \ifnum\@anim@first>\@anim@last\relax% \edef\@anim@every{-\@anim@every}% \def\@anim@relop{<}% \let\@anim@numtemplate\@anim@last% \fi% \global\@anim@curframe=\@anim@first% \global\@anim@curframe@zb=\z@% \if@anim@export% \def\@anim@method{\tw@}% \setboolean{@anim@controls}{false}% \setboolean{@anim@draft}{false}% \fi% \if@anim@dvisvgm% \def\@anim@method{\tw@}% using ocg-like method for dvisvgm \fi% \if@anim@draft% \if@anim@multipage% %store file in a box \@anim@filebox{\@anim@pathtofile}{\@anim@first}{\@anim@gropts}{\@anim@box}% \else% %get file name extension \@anim@getpath{\@anim@base\@anim@first}{\@anim@ftype}% \@anim@filebox{\@anim@pathtofile}{1}{\@anim@gropts}{\@anim@box}% \fi% \@anim@scale{\@anim@box}% %draw draftbox according to dimensions of the first frame \@anim@draftbox% \else% \xdef\@anim@nfps{#2\space}% current frame rate \xdef\@anim@nfps{\expandafter\@anim@zap@space\@anim@nfps\@empty}% \ifdim\@anim@nfps pt<\z@% \PackageError{animate}{% Negative frame rate `\@anim@nfps' is not allowed% }{}% \fi% \global\let\@anim@fps\@anim@nfps% % \if@anim@export% \anim@export% \fi% %embed content (graphics 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}{\@anim@gropts}% \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}{\@anim@gropts}% \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 %make animation frames from embedded content ... \if@anim@dvisvgm\ifcsname a\the\@anim@num.htbp\endcsname% \@anim@beginsvgclip{\the\@anim@num}% \fi\fi% \if@anim@timeline% ... by building timeline (optional timeline file) \@anim@buildtmln{\the\@anim@num}% \else% ... or by direct insertion \global\@anim@curframe@zb=\z@% \whiledo{\@anim@curframe@zb<\@anim@frames}{% \@anim@makeframe{\the\@anim@num}{\the\@anim@curframe@zb}{% \@anim@getkeyval{img@\the\@anim@curframe@zb},% }% \global\advance\@anim@curframe@zb by \@ne% }% \fi% \if@anim@dvisvgm\ifcsname a\the\@anim@num.htbp\endcsname% \@anim@endsvgclip% \fi\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 \if@anim@export\else% % insert <script> part \if@anim@dvisvgm\@anim@script{\the\@anim@num}\fi% \edef\@anim@btnattrs{% \@anim@bgcolour:\@anim@fgcolour:\@anim@alpha% \if@anim@dvisvgm:\@anim@btnsize:\@anim@abspage\fi% \@anim@lscape% }% \@anim@insertwidgets{\the\@anim@num}{\@anim@btnattrs}% \fi% \fi% \@anim@endLTR% \endgroup% \global\advance\@anim@num by \@ne% }% %adjust catcode of `:' character within \animategraphics \let\@anim@animategraphics\animategraphics \def\animategraphics{\@anim@sanitizeColon\@anim@animategraphics} %inserts animation and control button widgets \newboolean{@anim@controls@firstgrp} \def\@anim@insertwidgets#1#2{%#1:@anim@num, #2 btn colour, alpha, ... \vtop{% \offinterlineskip% \hbox{\@anim@animwidget{#1}}% \if@anim@controls% \setlength{\@anim@tmpdima}{\@anim@btnsize}% \vskip 0.1\@anim@tmpdima% \hbox to \@anim@animwidth {% \if@anim@ctrlleft\hspace{\@anim@ctrlsindent}\fi% \ifnum\if@anim@ctrlright\@ne\else% \if@anim@ctrlcentre\@ne\else\z@\fi\fi=\@ne\hss\fi% \def\@anim@tooltip{}% \setboolean{@anim@controls@firstgrp}{false}% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \@anim@makebutton{EndLeft}{#2}% \@anim@buttonwidget{#1}{EndLeft}{EndLeft:#2}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \@anim@makebutton{StepLeft}{#2}% \@anim@buttonwidget{#1}{StepLeft}{StepLeft:#2}% \fi% \if@anim@controls@play% \setboolean{@anim@controls@firstgrp}{true}% \@anim@makebutton{PauseLeft}{#2}% \@anim@buttonwidget{#1}{PauseLeft}{PauseLeft:#2}% \@anim@makebutton{PlayLeft}{#2}% \@anim@buttonwidget{#1}{PlayLeft}{PlayLeft:#2}% \@anim@buttonwidget{#1}{PlayPauseLeft}{}% \@anim@makebutton{PauseRight}{#2}% \@anim@buttonwidget{#1}{PauseRight}{PauseRight:#2}% \@anim@makebutton{PlayRight}{#2}% \@anim@buttonwidget{#1}{PlayRight}{PlayRight:#2}% \@anim@buttonwidget{#1}{PlayPauseRight}{}% \fi% \if@anim@controls@step% \setboolean{@anim@controls@firstgrp}{true}% \@anim@makebutton{StepRight}{#2}% \@anim@buttonwidget{#1}{StepRight}{StepRight:#2}% \fi% \if@anim@controls@stop% \setboolean{@anim@controls@firstgrp}{true}% \@anim@makebutton{EndRight}{#2}% \@anim@buttonwidget{#1}{EndRight}{EndRight:#2}% \fi% \if@anim@controls@speed% \if@anim@controls@firstgrp\hskip 0.3\@anim@tmpdima\fi% \def\@anim@tooltip{/TU (slower)}% \@anim@makebutton{Minus}{#2}% \@anim@buttonwidget{#1}{Minus}{Minus:#2}% \def\@anim@tooltip{/TU (default speed)}% \@anim@makebutton{Reset}{#2}% \@anim@buttonwidget{#1}{Reset}{Reset:#2}% \def\@anim@tooltip{/TU (faster)}% \@anim@makebutton{Plus}{#2}% \@anim@buttonwidget{#1}{Plus}{Plus:#2}% \fi% \ifnum\if@anim@ctrlleft\@ne\else% \if@anim@ctrlcentre\@ne\else\z@\fi\fi=\@ne\hss\fi% \if@anim@ctrlright\hspace{\@anim@ctrlsindent}\fi% }% \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% %now resize \ifcase\@anim@resizeflags% bit 2^2=width, 2^1=height, 2^0=totalhight given \or% 1 \setbox#1=\hbox{\resizebox*{!}{\@anim@animtotalheight}{\box#1}}% \or% 2 \setbox#1=\hbox{\resizebox{!}{\@anim@animheight}{\box#1}}% \or\or% 4 \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% \setbox#1=\hbox{\resizebox*{\@anim@animwidth}{!}{\box#1}}% \else% \setbox#1=\hbox{% \resizebox*{!}{\@anim@animtotalheight}{\box#1}}% \fi% \else% \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% \setbox#1=\hbox{\resizebox{\@anim@animwidth}{!}{\box#1}}% \else% \setbox#1=\hbox{\resizebox{!}{\@anim@animheight}{\box#1}}% \fi% \else% \setbox#1=\hbox{% \resizebox{\@anim@animwidth}{\@anim@animheight}{\box#1}}% \fi% \fi% %apply scale \ifdim\@anim@boxscale pt=\p@\else% \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 \if@anim@dvisvgm \def\@anim@animwidget#1{% \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% \@anim@annot{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% id='anm#1' \if@anim@nomouse\else cursor='pointer' \fi% }% \@anim@updatebbox{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}% \hbox to \@anim@animwidth {% \vrule width \z@ height \@anim@animheight depth \@anim@animdepth% \hss% }% } \else \def\@anim@animwidget#1{% \@anim@pojscript{#1}% \@anim@pcjscript{#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}{1}{}{}{\@anim@box}% \global\let\@anim@apdummy\@anim@lastxform% \@anim@widget{1ex}{1ex}{\z@}{% /Subtype/Widget% /F 2% /FT/Btn/Ff 65537% /BS <</W 0>>% /AP <</N \@anim@lastxform>>% /MK <</TP 1/I \@anim@lastxform/IF<</S/A/FB true>>>>% /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}{1}{}{}{\@anim@box}% \global\let\@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@annot{1ex}{1ex}{\z@}{% /Subtype/Screen/F 2% /AA <<% /PV <</S/JavaScript/JS \@anim@pojscriptobj>>% PageVisible /PO <</S/JavaScript/JS \@anim@pojscriptobj>>% PageOpen /PI <</S/JavaScript/JS \@anim@pcjscriptobj>>% PageInvisible /PC <</S/JavaScript/JS \@anim@pcjscriptobj>>% PageClose >>% }% \@anim@widget{\@anim@animwidth}{\@anim@animheight}{\@anim@animdepth}{% /Subtype/Widget% /FT/Btn/Ff \if@anim@nomouse 65537\else 65536\fi% \@anim@annotflag% /BS <</W 0>>% /H/N% /T (anm#1)% \@anim@alttext% %/Contents (...) /AA <<% /PV <</S/JavaScript/JS \@anim@pojscriptobj>>% PageVisible /PO <</S/JavaScript/JS \@anim@pojscriptobj>>% PageOpen /PI <</S/JavaScript/JS \@anim@pcjscriptobj>>% PageInvisible /PC <</S/JavaScript/JS \@anim@pcjscriptobj>>% PageClose \if@anim@nomouse\else% /D <</S/JavaScript/JS (\@anim@wdgtDownJS{#1})>>% mouse-down /U <</S/JavaScript/JS (\@anim@wdgtUpJS{#1})>>% mouse-up \fi% >>% /AP <</N \@anim@apmk>>% /MK <</TP 1/I \@anim@apmk/IF<</S/A/FB true>>>>% }% \hbox to \@anim@animwidth {% \vrule width \z@ height \@anim@animheight depth \@anim@animdepth% \hss% }% } \fi %creates control button widget \newboolean{@anim@js} \newboolean{@anim@mk} \if@anim@dvisvgm \def\@anim@buttonwidget#1#2#3{% #1:@anim@num, #2:action, % #3:button face and colour combination \def\@anim@arg{#2}\@anim@jstrue% \ifx\@anim@PlayLeft\@anim@arg% \@anim@jsfalse% \@anim@newocg{#1}{PlayLeft}% \fi% \ifx\@anim@PauseLeft\@anim@arg% \@anim@jsfalse% \@anim@newocg{#1}{PauseLeft}% \ocgbase@add@to@off@list{\@anim@curocg}% \fi% \ifx\@anim@PlayRight\@anim@arg% \@anim@jsfalse% \@anim@newocg{#1}{PlayRight}% \fi% \ifx\@anim@PauseRight\@anim@arg% \@anim@jsfalse% \@anim@newocg{#1}{PauseRight}% \ocgbase@add@to@off@list{\@anim@curocg}% \fi% % insert button face \if@anim@js% \ifx\@empty#3\@empty\else% PlayPauseLeft/PlayPauseRight don't have btn \@anim@refxform{\@anim@getkeyval{btn#3}}% % faces \fi% \else% PlayLeft, PauseLeft, PlayRight, PauseRight \ocgbase@oc@bdc{\@anim@curocg}% \@anim@refxform{\@anim@getkeyval{btn#3}}% \ocgbase@oc@emc% \fi% % insert widget \if@anim@js% \@anim@annot{\@anim@btnsize}{\@anim@btnsize}{\z@}{% cursor='pointer' onmousedown='% event.preventDefault();event.stopPropagation();% \@anim@btnJS{#1}{\@anim@arg}% '% }% \@anim@updatebbox{\@anim@btnsize}{\@anim@btnsize}{0pt}% \hbox to \@anim@btnsize {% \vrule width \z@ height \@anim@btnsize depth \z@% \hss% }% \fi% } \else \def\@anim@buttonwidget#1#2#3{%#1:@anim@num, #2:action, %#3:button face and colour+alpha+... combination \edef\@anim@arg{#2}\@anim@jstrue\@anim@mktrue% \def\@anim@annotflag{/F 0}% visible, but don't print \ifx\@anim@PlayLeft\@anim@arg\@anim@jsfalse\fi% %hidden, don't print | \ifx\@anim@PauseLeft\@anim@arg\@anim@jsfalse\def\@anim@annotflag{/F 2}\fi%_| \ifx\@anim@PlayRight\@anim@arg\@anim@jsfalse\fi% \ifx\@anim@PauseRight\@anim@arg\@anim@jsfalse\def\@anim@annotflag{/F 2}\fi% \ifx\@anim@PlayPauseLeft\@anim@arg\@anim@mkfalse\fi% \ifx\@anim@PlayPauseRight\@anim@arg\@anim@mkfalse\fi% \if@anim@mk\else% \ifdefined\@anim@apdummy\else% empty appearance dummy \setbox\@anim@box=\hbox{\phantom{x}}% \@anim@xform{0}{1}{}{}{\@anim@box}% \global\let\@anim@apdummy\@anim@lastxform% \fi% \fi% \@anim@widget{\@anim@btnsize}{\@anim@btnsize}{\z@}{% /Subtype/Widget% \@anim@annotflag% /FT/Btn/Ff \if@anim@js 65536\else 65537\fi% /H\if@anim@js/I\else/N\fi% /BS <</W 0>>% \if@anim@mk% /AP <</N \@anim@getkeyval{btn#3}>>% /MK <</TP 1/I \@anim@getkeyval{btn#3}/IF<</S/A/FB true>>>>% \else% /AP <</N \@anim@apdummy>>% /MK <</TP 1/I \@anim@apdummy/IF<</S/A/FB true>>>>% \fi% /T (#1.#2)% \@anim@tooltip% \if@anim@js% /AA <</D <</S/JavaScript/JS (\@anim@btnJS{#1}{\@anim@arg})>>>>% \fi% }% \if@anim@js% \hbox to \@anim@btnsize {% \vrule width \z@ height \@anim@btnsize depth \z@% \hss% }% \fi% } \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% \if@anim@export\else\leavevmode\fi% \@anim@reset% to default settings \if@anim@dvisvgm% \special{dvisvgm:raw <!-- animation by LaTeX-package `animate', https://ctan.org/tex-archive/macros/latex/contrib/animate, v. \@anim@version\space-->% }% \fi% \begingroup% \@anim@beginLTR% \ifdefined\NoHyper\NoHyper\fi% silently suppress any hyperref specials \ifcsname Ginput@path\endcsname% make use of graphic[xs] search path \let\input@path\Ginput@path% \fi% \SetKeys[anim@user]{#1}% %store current abs. page num in macro \@anim@abspage \if@anim@dvisvgm\if@anim@draft\else% \zref@labelbyprops{anim@abspage\the\@anim@num}{abspage}% \zref@def@extractdefault{\@anim@abspage}{% anim@abspage\the\@anim@num}{abspage}{-1}% \fi\fi% \ifx\empty\@anim@bg\empty\xdef\@anim@alpha{}\fi% \xdef\@anim@btnsize{\the\dimexpr\@anim@btnsize\relax}% %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% \ifthenelse{\boolean{@anim@autoplay}\OR\boolean{@anim@autoresume}}{% \setboolean{@anim@autoplayorresume}{true}% }{}% \ifthenelse{\NOT\boolean{@anim@controls}\AND\boolean{@anim@step}}{% \setboolean{@anim@loop}{true}% }{}% \if@anim@step% %for stepping animations, ignore any `controls' settings except \setboolean{@anim@controls@play}{false}% `step' and `stop' \setboolean{@anim@controls@speed}{false}% \setboolean{@anim@controls}{false}% \if@anim@controls@stop\setboolean{@anim@controls}{true}\fi% \if@anim@controls@step\setboolean{@anim@controls}{true}\fi% \fi% \global\@anim@curframe@zb=\z@% \global\@anim@skipfram=\z@% \if@anim@export% \def\@anim@method{\tw@}% \setboolean{@anim@controls}{false}% \setboolean{@anim@draft}{false}% \fi% \if@anim@dvisvgm% \def\@anim@method{\tw@}% \fi% \if@anim@draft\else% \if@anim@step\else% \xdef\@anim@nfps{-1}% \@anim@processfpsarg{#2}% \fi% \if@anim@export% \anim@export% \fi% \fi% \let\newframe\@anim@@newframe% \let\multiframe\@anim@multiframe% \@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 \global\@anim@tmpcnt=\@anim@frames% \global\advance\@anim@tmpcnt by -\@ne% \xdef\@anim@maxframe{\the\@anim@tmpcnt}% highest frame index %make animation frames from embedded content ... \if@anim@dvisvgm\ifcsname a\the\@anim@num.htbp\endcsname% \@anim@beginsvgclip{\the\@anim@num}% \fi\fi% \if@anim@timeline% ... by building timeline (optional timeline file) \@anim@buildtmln{\the\@anim@num}% \else% ... or by direct insertion \global\@anim@curframe@zb=\z@% \whiledo{\@anim@curframe@zb<\@anim@frames}{% \@anim@makeframe{\the\@anim@num}{\the\@anim@curframe@zb}{% \@anim@getkeyval{img@\the\@anim@curframe@zb},% }% \global\advance\@anim@curframe@zb by \@ne% }% \fi% \if@anim@dvisvgm\ifcsname a\the\@anim@num.htbp\endcsname% \@anim@endsvgclip% \fi\fi% %insert animation widget & controls \if@anim@export\else% % insert <script> part \if@anim@dvisvgm\@anim@script{\the\@anim@num}\fi% \edef\@anim@btnattrs{% \@anim@bgcolour:\@anim@fgcolour:\@anim@alpha% \if@anim@dvisvgm:\@anim@btnsize:\@anim@abspage\fi% \@anim@lscape% }% \@anim@insertwidgets{\the\@anim@num}{\@anim@btnattrs}% \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% \fi% \ifdefined\endNoHyper\endNoHyper\fi% \@anim@endLTR% \endgroup% \global\advance\@anim@num by \@ne% } \let\@anim@animateinline\animateinline \def\animateinline{\@anim@sanitizeColon\@anim@animateinline} % clip animation to final dimensions (dvisvgm) \def\@anim@beginsvgclip#1{% \special{dvisvgm:raw <svg overflow="hidden" x="{?x}" y="{?(y-\@anim@getkeyval{a#1.htbp})}" width="\@anim@getkeyval{a#1.wdbp}" height="\@anim@getkeyval{a#1.thtbp}" viewBox="% {?x} {?(y-\@anim@getkeyval{a#1.htbp})} \@anim@getkeyval{a#1.wdbp} \@anim@getkeyval{a#1.thtbp}% ">% }% }% \def\@anim@endsvgclip{% \special{dvisvgm:raw </svg>}% } %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 \global\let\@anim@pfps\@anim@nfps% \xdef\@anim@nfps{#1\space}% \xdef\@anim@nfps{\expandafter\@anim@zap@space\@anim@nfps\@empty}% \ifx\@anim@nfps\@empty% no change of frame rate \global\let\@anim@nfps\@anim@pfps% \fi% \ifnum\@anim@curframe@zb=\z@\relax% \global\let\@anim@fps\@anim@nfps% default fps \global\let\@anim@nfpsat\@anim@nfps% \else% \xdef\@anim@nfpsat{\@anim@nfpsat,\@anim@nfps}% \fi% \ifdim\@anim@nfps pt=\@anim@pfps pt\else% \ifnum\@anim@curframe@zb=\z@\relax\else% \setboolean{@anim@chfps}{true}% change fps \fi% \fi% \ifdim\@anim@nfps pt<\z@% \PackageError{animate}{% Negative frame rate `\@anim@nfps' is not allowed% }{}% \fi% }% \newcommand{\@anim@newframe}[1][]{% #1: new frame rate \ifnum\@anim@skipfram=\z@\relax% \global\advance\@anim@curframe@zb by \@ne% \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %process frame rate argument \@anim@processfpsarg{#1}% \fi% \fi% \fi% \fi% \@anim@beginframe% \ignorespaces% } \newcommand{\@anim@newframestar}[1][]{% starred variant for pausing animation \ifnum\@anim@skipfram=\z@\relax% #1: new frame rate \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %build JavaScript commands to fill the `pauseAt' array \xdef\@anim@pauseat{% \@anim@pauseat% a\the\@anim@num_pauseAt[\the\@anim@curframe@zb]=1;% }% \setboolean{@anim@pauseframes}{true}% \fi% \fi% \fi% \global\advance\@anim@curframe@zb by \@ne% \if@anim@draft\else% \if@anim@step\else% \if@anim@timeline\else% %process frame rate argument \@anim@processfpsarg{#1}% \fi% \fi% \fi% \fi% \@anim@beginframe% \ignorespaces% } %starts new frame \def\@anim@beginframe{% \begingroup% \lrbox{\@anim@box}% store graphics in a box \ifdefined\@anim@curTxtDir\textdir\@anim@curTxtDir\fi% \@anim@begin% } %terminates current frame \def\@anim@endframe#1#2{% \@anim@end% \endlrbox% \endgroup% \ifnum\@anim@skipfram=\z@\relax% \ifnum#2=\z@\relax% \ifdim\wd\@anim@box=\z@% \PackageError{animate}{% Content 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}{% Content 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@\setbox\@anim@box=\hbox{\phantom{X}}\fi% \ifdim\ht\@anim@box=\z@\ifdim\dp\@anim@box=\z@% \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}{inline}% \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\@anim@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% \if@anim@draft% \global\@anim@mulframecnt=#1% \else% \def\multiframebreak{\global\@anim@mulframecnt=#1}% \fi% \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 %initialise 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 %initialise 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 %initialise 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_are_unused_animation_transparencies._@\MessageBreak% @_See_the_transcript_file____________________@\MessageBreak% @___``\jobname.log''\MessageBreak% @_for_additional_information!________________@\MessageBreak% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% } \endgroup %macros for sanitizing characters \def\@anim@sanitize#1#2\@nil{% \catcode`#1=12% \ifx\@empty#2\@empty\else% \@anim@sanitize#2\@nil% \fi% } \def\@anim@sanitizeJS{% sanitize JS code while being read from timeline file \begingroup% \@anim@sanitize.:;?!/"'*+,->=<$\&@][)(^_`|~\#\@nil% \def\\{\string\\}% \def\{{\string\{}% \def\}{\string\}}% \def\%{\string\%}% } \def\@anim@sanitizeColon{% sanitize colon (`:') while reading the option list, \begingroup% in particular the `buttonfg' and `buttonbg' options \@anim@sanitize:\@nil% arguments } \let\@anim@endsanitize\endgroup %building timeline from timeline file \newread\@anim@@tmlnfile \newboolean{@anim@eof} \newcount\@anim@tmpcnt %scratch counter for different uses \newcounter{@anim@ltxcnt} %scratch LaTeX counter for different uses \newcount\@anim@curlayer %takes the number of the current layer being processed \newcount\@anim@lineno %current input line No. \newcount\@anim@curfield %current field of input line processed \def\@anim@buildtmln#1{% #1:@anim@num \global\@anim@curframe@zb=\z@% %read timeline file a first time to get number of lines (= number of frames) \openin\@anim@@tmlnfile=\@anim@tmlnfile% \@anim@sanitizeJS% \endlinechar=-1% suppress trailing space at input line end \global\read\@anim@@tmlnfile to \@anim@inputline% \@anim@endsanitize% \edef\@anim@inputline{\@anim@inputline\space}% %remove all spaces from input line \edef\@anim@inputline{\expandafter\@anim@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}{}}{}{% \global\advance\@anim@curframe@zb by \@ne% }% \@anim@sanitizeJS% \endlinechar=-1% suppress trailing space at input line end \global\read\@anim@@tmlnfile to \@anim@inputline% \@anim@endsanitize% \edef\@anim@inputline{\@anim@inputline\space}% \edef\@anim@inputline{\expandafter\@anim@zap@space\@anim@inputline\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% }% \closein\@anim@@tmlnfile% \global\let\@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@% \@anim@sanitizeJS% \endlinechar=-1% suppress trailing space at input line end \global\read\@anim@@tmlnfile to \@anim@inputline% \@anim@endsanitize% \edef\@anim@inputlinenospc{\@anim@inputline\space}% \edef\@anim@inputlinenospc{% \expandafter\@anim@zap@space\@anim@inputlinenospc\@empty}% \ifeof\@anim@@tmlnfile\setboolean{@anim@eof}{true}\else% \setboolean{@anim@eof}{false}\fi% \message{<building timeline a#1 from file `\@anim@tmlnfile':}% \whiledo{\NOT\boolean{@anim@eof}}{% \global\advance\@anim@lineno by \@ne% %initialise content and transparency lists for current frame \def\@anim@frmcontent{}% \def\@anim@trlst{}% \ifthenelse{\equal{\@anim@inputlinenospc}{}}{}{% %process input line \global\@anim@curfield=\z@% \expandafter\@anim@parseline\@anim@inputline:\@nil% %combine the layers of the current frame \global\@anim@curlayer=\z@% \loop\ifnum\@anim@curlayer>\@anim@maxlayer\relax\else% \edef\@anim@frmcontent{% \@anim@frmcontent% \@anim@getkeyval{% layercontent@\the\@anim@curframe@zb.\the\@anim@curlayer}% }% \edef\@anim@trlst{% \@anim@trlst% \@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 \xdef\@anim@@trlst{\the\@anim@curframe@zb.\@anim@trlst}% \expandafter\@anim@findmult\@anim@@trlst,\@nil% %insert frame Widget \@anim@makeframe{#1}{\the\@anim@curframe@zb}{\@anim@frmcontent}% %clean-up \expandafter\@anim@resetmult\@anim@@trlst,\@nil% \message{.}% \global\advance\@anim@curframe@zb by \@ne% }% \@anim@sanitizeJS% \endlinechar=-1% suppress trailing space at input line end \global\read\@anim@@tmlnfile to \@anim@inputline% \@anim@endsanitize% \edef\@anim@inputlinenospc{\@anim@inputline\space}% \edef\@anim@inputlinenospc{% \expandafter\@anim@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\@anim@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\@anim@zap@space\@anim@tmp\@empty}% \expandafter\@anim@parsethird\@anim@tmp;\@nil% \edef\@anim@tmp{#2\space}% \edef\@anim@tmp{\expandafter\@anim@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\@anim@zap@space\@anim@tmp\@empty}% \ifx\@anim@tmp\@empty\else% \xdef\@anim@usrjsat{% \@anim@usrjsat% a\the\@anim@num_usrJS[\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 \let\@anim@repeatuntil\@anim@frames% \else% \global\@anim@tmpcnt=\@anim@curframe@zb% \global\advance\@anim@tmpcnt by \@anim@repeats% \ifnum\@anim@frames<\@anim@tmpcnt\relax% \let\@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% }% } \def\@anim@zap@space#1 #2{% #1% \ifx#2\@empty\else\expandafter\@anim@zap@space\fi #2% } %command options \newboolean{@anim@iso} \newboolean{@anim@hiresbb} \newboolean{@anim@interpolate} \newboolean{@anim@controls} \newboolean{@anim@controls@play} \newboolean{@anim@controls@step} \newboolean{@anim@controls@stop} \newboolean{@anim@controls@speed} \newboolean{@anim@ctrlleft} \newboolean{@anim@ctrlright} \newboolean{@anim@ctrlcentre} \newboolean{@anim@loop} \newboolean{@anim@autoplay} \newboolean{@anim@autoresume} \newboolean{@anim@autopause} \newboolean{@anim@palindrome} \newboolean{@anim@step} \newboolean{@anim@meas} \setboolean{@anim@nomouse}{false} \newboolean{@anim@draft} \def\@anim@mone{-1}\def\@anim@mtwo{-2} \def\@anim@user@controls@all{% \setboolean{@anim@controls}{true}% \setboolean{@anim@controls@play}{true}% \setboolean{@anim@controls@step}{true}% \setboolean{@anim@controls@stop}{true}% \setboolean{@anim@controls@speed}{true}% } \def\@anim@user@controls@none{% \setboolean{@anim@controls}{false}% \setboolean{@anim@controls@play}{false}% \setboolean{@anim@controls@step}{false}% \setboolean{@anim@controls@stop}{false}% \setboolean{@anim@controls@speed}{false}% } \def\@anim@parse@ctrlsalignarg#1#2#3+#4\@nil{% \ifthenelse{\equal{#3}{}}{}{\def#1{#3}}% \ifthenelse{\equal{#4}{}}{#2=\z@}{\@anim@getalignindent#2#4\@nil}% } \def\@anim@getalignindent#1#2+\@nil{#1=#2} % helper macro to get number of colour components \def\@anim@colours#1{\@anim@@colours#1:\@nil} \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% }% } \ExplSyntaxOn \DeclareKeys[anim@user]{ label.code:n = { \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~are~multiply-defined~labels!~@\MessageBreak @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@} } \fi \fi \expandafter\gdef\csname @anim@#1\endcsname{} }, label.value_required:n = true, width.code:n = { \gdef\@anim@widtharg{#1} \ifdefined\@anim@usrwd\else \global\advance\@anim@resizeflags by 4 \def\@anim@usrwd{} \fi }, width.value_required:n = true, height.code:n = { \gdef\@anim@heightarg{#1} \ifdefined\@anim@usrht\else \global\advance\@anim@resizeflags by 2 \def\@anim@usrht{} \fi }, height.value_required:n = true, totalheight.code:n = { \gdef\@anim@totheightarg{#1} \ifdefined\@anim@usrtht\else \global\advance\@anim@resizeflags by \@ne \def\@anim@usrtht{} \fi }, totalheight.value_required:n = true, keepaspectratio.legacy_if_gset:n = @anim@iso, keepaspectratio.default:n = true, bb.code:n = {\xdef\@anim@bb{bb=#1}}, bb.value_required:n = true, viewport.code:n = {\xdef\@anim@viewport{viewport=#1}}, viewport.value_required:n = true, trim.code:n = {\xdef\@anim@trim{trim=#1}}, trim.value_required:n = true, angle.code:n = {\xdef\@anim@angle{angle=#1}}, angle.value_required:n = true, pagebox.code:n = {\xdef\@anim@pagebox{pagebox=#1}}, pagebox.value_required:n = true, clip.code:n = {}, % no-op, as embedded graphics are always clip.default:n = true, % clipped to widget box hiresbb.legacy_if_gset:n = @anim@hiresbb, hiresbb.default:n = true, interpolate.legacy_if_gset:n = @anim@interpolate, interpolate.default:n = true, scale.tl_gset_x:N = \@anim@boxscale, scale.value_required:n = true, buttonsize.tl_gset:N = \@anim@btnsize, buttonsize.value_required:n = true, buttonbg.code:n = { \global\@anim@tmpcnt=\@ne \gdef\@anim@colour{} \@anim@colours{#1} \global\let\@anim@bgcolour\@anim@colour \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 \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 }, buttonbg.value_required:n = true, buttonfg.code:n = { \global\@anim@tmpcnt=\@ne \gdef\@anim@colour{} \@anim@colours{#1} \global\let\@anim@fgcolour\@anim@colour \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 \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 }, buttonfg.value_required:n = true, buttonalpha.tl_gset_x:N = \@anim@alpha, buttonalpha.value_required:n = true, alttext.code:n = { \ifthenelse{\equal{#1}{none}}{ \gdef\@anim@alttext{} }{ \xdef\@anim@alttext{/Contents~(#1)} } }, alttext.value_required:n = true, controls.multichoice:, controls / all.code:n = {\@anim@user@controls@all}, controls / true.code:n = {\@anim@user@controls@all}, controls / on.code:n = {\@anim@user@controls@all}, controls / none.code:n = {\@anim@user@controls@none}, controls / false.code:n = {\@anim@user@controls@none}, controls / off.code:n = {\@anim@user@controls@none}, controls / play.code:n = { \setboolean{@anim@controls}{true} \setboolean{@anim@controls@play}{true} }, controls / step.code:n = { \setboolean{@anim@controls}{true} \setboolean{@anim@controls@step}{true} }, controls / stop.code:n = { \setboolean{@anim@controls}{true} \setboolean{@anim@controls@stop}{true} }, controls / speed.code:n = { \setboolean{@anim@controls}{true} \setboolean{@anim@controls@speed}{true} }, controls.default:n = all, controlsaligned.code:n = { \@anim@parse@ctrlsalignarg\@anim@tmpvar\@anim@tmpdima#1+\@nil \ifthenelse{\equal{\@anim@tmpvar}{left}}{ \setboolean{@anim@ctrlleft}{true} \setboolean{@anim@ctrlright}{false} \setboolean{@anim@ctrlcentre}{false} \xdef\@anim@ctrlsindent{\the\@anim@tmpdima} }{ \ifthenelse{\equal{\@anim@tmpvar}{right}}{ \setboolean{@anim@ctrlleft}{false} \setboolean{@anim@ctrlright}{true} \setboolean{@anim@ctrlcentre}{false} \xdef\@anim@ctrlsindent{\the\@anim@tmpdima} }{ \ifthenelse{\equal{\@anim@tmpvar}{center}}{ \setboolean{@anim@ctrlleft}{false} \setboolean{@anim@ctrlright}{false} \setboolean{@anim@ctrlcentre}{true} \xdef\@anim@ctrlsindent{\z@} }{} } } }, controlsaligned.value_required:n = true, loop.legacy_if_gset:n = @anim@loop, loop.default:n = true, autoplay.code:n = { \setboolean{@anim@autoplay}{#1} \if@anim@autoplay\setboolean{@anim@autoresume}{false}\fi }, autoplay.default:n = true, autoresume.code:n = { \setboolean{@anim@autoresume}{#1} \if@anim@autoresume\setboolean{@anim@autoplay}{false}\fi }, autoresume.default:n = true, autopause.legacy_if_gset:n = @anim@autopause, autopause.default:n = true, palindrome.legacy_if_gset:n = @anim@palindrome, palindrome.default:n = true, poster.choice:, % <num> | first | last | none poster / first.code:n = {\gdef\@anim@poster{0}}, poster / last.code:n = {\gdef\@anim@poster{-1}}, poster / none.code:n = {\gdef\@anim@poster{-2}}, poster / unknown.code:n = {% frame <num> \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} }, poster.default:n = first, step.legacy_if_gset:n = @anim@step, step.default:n = true, draft.legacy_if_gset:n = @anim@draft, draft.default:n = true, final.code:n = { \ifthenelse{\equal{#1}{true}}{ \setboolean{@anim@draft}{false} }{ \setboolean{@anim@draft}{true} } }, final.default:n = true, nomouse.legacy_if_gset:n = @anim@nomouse, nomouse.default:n = true, timeline.code:n = { \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! } } }, timeline.value_required:n = true, begin.tl_gset:N = \@anim@begin, begin.value_required:n = true, end.tl_gset:N = \@anim@end, end.value_required:n = true, every.code:n = { \ifnum#1<\@ne\relax\gdef\@anim@every{1}\else\gdef\@anim@every{#1}\fi }, every.value_required:n = true, measure.legacy_if_gset:n = @anim@meas, measure.default:n = true, method.choices:nn = {icon,widget,ocg} { \ifthenelse{\equal{#1}{icon}}{ \def\@anim@method{\z@} }{ \ifthenelse{\equal{#1}{widget}}{ \def\@anim@method{\@ne} }{ \ifthenelse{\equal{#1}{ocg}}{ \def\@anim@method{\tw@} }{} } } }, method.value_required:n = true, type.tl_gset_x:N = \@anim@ftype, type.value_required:n = true, } \ExplSyntaxOff %macro to reset macros and booleans \def\@anim@reset{% \gdef\@anim@label{}% \global\let\@anim@boxscale\@anim@@boxscale% \global\let\if@anim@iso=\if@anim@@iso% \global\let\@anim@bb\@anim@@bb% \global\let\@anim@viewport\@anim@@viewport% \global\let\@anim@trim\@anim@@trim% \global\let\@anim@angle\@anim@@angle% \global\let\if@anim@hiresbb=\if@anim@@hiresbb% \global\let\if@anim@interpolate=\if@anim@@interpolate% \global\let\@anim@pagebox\@anim@@pagebox% \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% \let\@anim@alttext\@anim@@alttext% \global\let\@anim@bg\@anim@@bg% \global\let\@anim@fg\@anim@@fg% \global\let\@anim@@@fg\@anim@@@@fg% \global\let\@anim@bgcolour\@anim@@bgcolour% default button colours \global\let\@anim@fgcolour\@anim@@fgcolour% \global\let\@anim@alpha\@anim@@alpha% \global\let\@anim@btnsize\@anim@@btnsize% \global\let\@anim@poster\@anim@@poster% \global\let\if@anim@controls=\if@anim@@controls% \global\let\if@anim@controls@play=\if@anim@@controls@play% \global\let\if@anim@controls@step=\if@anim@@controls@step% \global\let\if@anim@controls@stop=\if@anim@@controls@stop% \global\let\if@anim@controls@speed=\if@anim@@controls@speed% \global\let\if@anim@ctrlleft=\if@anim@@ctrlleft% \global\let\if@anim@ctrlright=\if@anim@@ctrlright% \global\let\if@anim@ctrlcentre=\if@anim@@ctrlcentre% \global\let\@anim@ctrlsindent\@anim@@ctrlsindent% \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% \global\let\@anim@method\@anim@@method% \global\let\if@anim@nomouse=\if@anim@@nomouse% \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}% \global\let\@anim@ftype\@anim@@ftype% } %package options \newcount\@anim@@resizeflags \def\@anim@@widtharg{\width} \def\@anim@@heightarg{\height} \def\@anim@@totheightarg{\totalheight} \newboolean{@anim@@iso} \def\@anim@@bb{} \def\@anim@@viewport{} \def\@anim@@trim{} \def\@anim@@angle{} \def\@anim@@pagebox{} \newboolean{@anim@@hiresbb} \newboolean{@anim@@interpolate} \def\@anim@@boxscale{1} \def\@anim@@btnsize{1.44em} \def\@anim@@bg{} \def\@anim@@bgcolour{} \def\@anim@@fgcolour{} \def\@anim@@alpha{} \edef\@anim@@alttext{/Contents (animation by animate, v. \@anim@version)} \newboolean{@anim@@controls} \newboolean{@anim@@controls@play} \newboolean{@anim@@controls@step} \newboolean{@anim@@controls@stop} \newboolean{@anim@@controls@speed} \def\@anim@pkg@controls@all{% \setboolean{@anim@@controls}{true}% \setboolean{@anim@@controls@play}{true}% \setboolean{@anim@@controls@step}{true}% \setboolean{@anim@@controls@stop}{true}% \setboolean{@anim@@controls@speed}{true}% } \def\@anim@pkg@controls@none{% \setboolean{@anim@@controls}{false}% \setboolean{@anim@@controls@play}{false}% \setboolean{@anim@@controls@step}{false}% \setboolean{@anim@@controls@stop}{false}% \setboolean{@anim@@controls@speed}{false}% } \newboolean{@anim@@ctrlleft} \newboolean{@anim@@ctrlright} \newboolean{@anim@@ctrlcentre} \setboolean{@anim@@ctrlcentre}{true} \def\@anim@@ctrlsindent{\z@} \newboolean{@anim@@loop} \newboolean{@anim@@autoplay} \newboolean{@anim@@autoresume} \newboolean{@anim@@autopause} \newboolean{@anim@@palindrome} \gdef\@anim@@poster{0}% \newboolean{@anim@@step} \newboolean{@anim@@draft} \ifdraft{%globally set by document class \setboolean{@anim@@draft}{true}% }{% \setboolean{@anim@@draft}{false}% } \newboolean{@anim@@nomouse} \def\@anim@@method{\z@}%default animation method is `icon' \def\@anim@@ftype{}% file type (extension) of graphics \ExplSyntaxOn \DeclareKeys[anim@pkg]{ width.code:n = { \gdef\@anim@@widtharg{#1} \ifdefined\@anim@pkgwd\else \advance\@anim@@resizeflags by 4 \def\@anim@pkgwd{}% \fi% }, width.value_required:n = true, height.code:n = { \gdef\@anim@@heightarg{#1} \ifdefined\@anim@pkght\else \advance\@anim@@resizeflags by 2 \def\@anim@pkght{} \fi }, height.value_required:n = true, totalheight.code:n = { \gdef\@anim@@totheightarg{#1} \ifdefined\@anim@pkgtht\else \advance\@anim@@resizeflags by \@ne \def\@anim@pkgtht{} \fi }, totalheight.value_required:n = true, keepaspectratio.legacy_if_gset:n = @anim@@iso, keepaspectratio.default:n = true, bb.code:n = {\xdef\@anim@@bb{bb=#1}}, bb.value_required:n = true, viewport.code:n = {\xdef\@anim@@viewport{viewport=#1}}, viewport.value_required:n = true, trim.code:n = {\xdef\@anim@@trim{trim=#1}}, trim.value_required:n = true, angle.code:n = {\xdef\@anim@@angle{angle=#1}}, angle.value_required:n = true, pagebox.code:n = {\xdef\@anim@@pagebox{pagebox=#1}}, pagebox.value_required:n = true, clip.code:n = {}, % no-op, as embedded graphics are always clip.default:n = true, % clipped to widget box hiresbb.legacy_if_gset:n = @anim@@hiresbb, hiresbb.default:n = true, interpolate.legacy_if_gset:n = @anim@@interpolate, interpolate.default:n = true, scale.tl_gset_x:N = \@anim@@boxscale, scale.value_required:n = true, buttonsize.tl_gset:N = \@anim@@btnsize, buttonsize.value_required:n = true, buttonbg.code:n = { \global\@anim@tmpcnt=\@ne \gdef\@anim@colour{} \@anim@colours{#1} \global\let\@anim@@bgcolour\@anim@colour \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 \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 }, buttonbg.value_required:n = true, buttonfg.code:n = { \global\@anim@tmpcnt=\@ne \gdef\@anim@colour{} \@anim@@colours#1:\@nil \global\let\@anim@@fgcolour\@anim@colour \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 \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 }, buttonfg.value_required:n = true, buttonalpha.tl_gset_x:N = \@anim@@alpha, buttonalpha.value_required:n = true, alttext.code:n = { \ifthenelse{\equal{#1}{none}}{ \gdef\@anim@@alttext{} }{ \xdef\@anim@@alttext{/Contents~(#1)} } }, alttext.value_required:n = true, controls.multichoice:, controls / all.code:n = {\@anim@pkg@controls@all}, controls / true.code:n = {\@anim@pkg@controls@all}, controls / on.code:n = {\@anim@pkg@controls@all}, controls / none.code:n = {\@anim@pkg@controls@none}, controls / false.code:n = {\@anim@pkg@controls@none}, controls / off.code:n = {\@anim@pkg@controls@none}, controls / play.code:n = { \setboolean{@anim@@controls}{true} \setboolean{@anim@@controls@play}{true} }, controls / step.code:n = { \setboolean{@anim@@controls}{true} \setboolean{@anim@@controls@step}{true} }, controls / stop.code:n = { \setboolean{@anim@@controls}{true} \setboolean{@anim@@controls@stop}{true} }, controls / speed.code:n = { \setboolean{@anim@@controls}{true} \setboolean{@anim@@controls@speed}{true} }, controls.default:n = all, controlsaligned.code:n = { \@anim@parse@ctrlsalignarg\@anim@tmpvar\@anim@tmpdima#1+\@nil \setboolean{@anim@@ctrlcentre}{false} \ifthenelse{\equal{\@anim@tmpvar}{left}}{ \setboolean{@anim@@ctrlleft}{true} \edef\@anim@@ctrlsindent{\the\@anim@tmpdima} }{ \ifthenelse{\equal{\@anim@tmpvar}{right}}{ \setboolean{@anim@@ctrlright}{true} \edef\@anim@@ctrlsindent{\the\@anim@tmpdima} }{ \setboolean{@anim@@ctrlcentre}{true} \xdef\@anim@@ctrlsindent{\z@} } } }, controlsaligned.value_required:n = true, loop.legacy_if_gset:n = @anim@@loop, loop.default:n = true, autoplay.code:n = { \setboolean{@anim@@autoplay}{#1} \if@anim@@autoplay\setboolean{@anim@@autoresume}{false}\fi }, autoplay.default:n = true, autoresume.code:n = { \setboolean{@anim@@autoresume}{#1} \if@anim@@autoresume\setboolean{@anim@@autoplay}{false}\fi }, autoresume.default:n = true, autopause.legacy_if_gset:n = @anim@@autopause, autopause.default:n = true, palindrome.legacy_if_gset:n = @anim@@palindrome, palindrome.default:n = true, poster.choice:, % <num> | first | last | none poster / first.code:n = {\gdef\@anim@@poster{0}}, poster / last.code:n = {\gdef\@anim@@poster{-1}}, poster / none.code:n = {\gdef\@anim@@poster{-2}}, poster / unknown.code:n = {% frame <num> \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} }, poster.default:n = first, step.legacy_if_gset:n = @anim@@step, step.default:n = true, draft.code:n = { \setboolean{@anim@@draft}{#1} \if@anim@export\setboolean{@anim@@draft}{false}\fi }, draft.default:n = true, final.code:n = { \ifthenelse{\equal{#1}{true}}{ \setboolean{@anim@@draft}{false} }{% \setboolean{@anim@@draft}{true} }% }, final.default:n = true, nomouse.legacy_if_gset:n = @anim@@nomouse, nomouse.default:n = true, method.choices:nn = {icon,widget,ocg} { \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 } } }, method.value_required:n = true, type.tl_gset_x:N = \@anim@@ftype, type.value_required:n = true, } \ExplSyntaxOff \ifnum\if@anim@dvips 1\else\if@anim@dvisvgm 1\else0\fi\fi=1 %dvips .OR. dvisvgm \def\@anim@@fg{0 setgray}\def\@anim@@@@fg{} \else% pdftex and dvipdfmx \def\@anim@@fg{0 G}\def\@anim@@@@fg{0 g} \fi %process package options \ProcessKeyOptions[anim@pkg] %%%%%%%%%%%%%%%%%%%%%%%% % JavaScript part %%%%%%%%%%%%%%%%%%%%%%%% %some JS engine specifics % PDF readers \def\@anim@consoleshow{console.show();} \def\@anim@app{app.} \def\@anim@setTimeout{setTimeOut} \def\@anim@log{println} \def\@anim@shift{shift} \if@anim@dvisvgm % web browsers \def\@anim@consoleshow{} \def\@anim@app{} \def\@anim@setTimeout{setTimeout} \def\@anim@log{log} \def\@anim@shift{shiftKey} \fi \begingroup % `$' --> newline in svg output \if@anim@dvisvgm %insert newline special \catcode`\$=\active\gdef${{?nl}} \else \catcode`$=\catcode`\% \fi %JS variable declarations \gdef\@anim@@jsvardecls#1{% #1: @anim@num var a#1_idx;$% animation frame index \ifnum\@anim@method>\z@% var a#1_on;$% add. index used by Widget and OCG methods \fi% %takes references to frame ocgs/Field objects belonging to the current %animation var a#1_fr;$% \ifnum\@anim@method=\z@ % icon based var a#1_wid;$% reference to interactive widget \ifnum\@anim@poster=\@anim@mtwo var blnk;$% \fi% \fi% \if@anim@controls@play% var a#1_btnPauseLeft,a#1_btnPlayLeft,a#1_btnPauseRight,a#1_btnPlayRight;$% \fi% var a#1_playsRight,a#1_isPaused\if@anim@step\else,a#1_playing\fi;$% \if@anim@step\else var a#1_int% timer id (takes return val of setIntervall()) \ifnum\@anim@poster>\z@% custom poster (frame _between_, i. e. ,a#1_posterOn% not including, first and last) \fi;$% % function pointers var a#1_pause,a#1_playRight,a#1_playLeft,a#1_playBwd,a#1_playFwd;$% \if@anim@pauseframes %this array takes the frame numbers at which to pause playback var a#1_pauseAt;$% \fi% \if@anim@chfps %arrays that take frame numbers (array index) and fps values var a#1_nFpsAt;$% \fi var a#1_fps,a#1_spd;$% frames per second (FPS), speed scaling factor var a#1_setFps;$% function pointer for setting FPS \if@anim@meas % speed measurement var spc=String.fromCharCode(32);$% var a#1_frcnt,% frame counter a#1_msStart,% takes start time (in millisecs) a#1_msEnd;$% takes end time (in millisecs) var a#1_startMeas,a#1_stopMeas;$% function pointers \fi% \fi% \if@anim@usrjs % array of function pointers to timeline JS actions, indexed by frame number var a#1_usrJS,a#1_curjs;$% \fi var a#1_seekFrame,a#1_gotoNext,a#1_gotoPrev;$% var a#1_stopFirst,a#1_stopLast;$% \if@anim@controls@play var a#1_playPauseBwd,a#1_playPauseFwd;$% \fi% \if@anim@controls@step var a#1_stepBwd,a#1_stepFwd;$% \fi% \if@anim@controls@speed var a#1_spdIncr,a#1_spdDecr,a#1_spdReset;$% \fi% \ifx\empty\@anim@label\empty\else var anim;$% \fi% } %JS initialisation \gdef\@anim@@jsinit#1{% #1: @anim@num \if@anim@dvisvgm\else var curdoc=this;\fi if(!a#1_fr){$% a#1_fr=new Array();$% \ifnum\@anim@method>\z@% a#1_on=0;$% \fi% \if@anim@step\else% \ifnum\@anim@poster>\z@% poster frame _between_ (i. e. non including) first a#1_posterOn=true;% and last \fi% \fi% \ifcase\@anim@method %icon based a#1_wid=this.getField('anm#1');$%reference to interactive widget for(var i=0;i<=\@anim@maxframe;i++){$% a#1_fr[i]=this.getField('#1.'+i).buttonGetIcon();$% }$% \ifnum\@anim@poster=\@anim@mtwo if(!blnk){$% blank poster (one for all animations) blnk=this.getField('0000').buttonGetIcon();$% }$% \fi% \or %widget based %get array of animation frames for(var i=0;i<=\@anim@maxframe;i++){$% a#1_fr[i]=this.getField('#1.'+i);$% }$% \or %ocg based %get array of ocgs of current page \if@anim@dvisvgm var ocg=document.getElementsByClassName('ocg');$% \else var ocg=this.getOCGs(this.pageNum);$% \fi for(var i=0;i<ocg.length;i++){$% \if@anim@dvisvgm % slice(1) --> remove leading underscore var ocgName=ocg[i].getAttribute('id').slice(1).split('.');$% \else var ocgName=ocg[i].name.split('.');$% \fi if(ocgName[0]==#1){$% %get array of animation frames a#1_fr[ocgName[1]]=ocg[i];$% %set basic frame state \if@anim@dvisvgm\else a#1_fr[ocgName[1]].state=ocg[i].initState;$% \fi% }$% }$% \fi% \if@anim@controls@play% \if@anim@dvisvgm a#1_btnPauseLeft=document.getElementById('_#1.PauseLeft');$% a#1_btnPlayLeft=document.getElementById('_#1.PlayLeft');$% a#1_btnPauseRight=document.getElementById('_#1.PauseRight');$% a#1_btnPlayRight=document.getElementById('_#1.PlayRight');$% \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 a#1_pauseAt=new Array();$% frame numbers at which to pause playback \@anim@pauseat% \fi% \if@anim@chfps %arrays that take frame numbers (array index) and fps values a#1_nFpsAt=new Array(\@anim@nfpsat);$% \fi \ifdim\@anim@fps pt=\z@% a#1_fps=1e-6;$% \else a#1_fps=\@anim@fps;$% \fi a#1_spd=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_usrJS=new Array();$% \@anim@usrjsat% populate array \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;$% \if@anim@dvisvgm a#1_fr[0].setAttribute('visibility','hidden');$% \else a#1_fr[0].state=false;$% \fi% \fi a#1_idx=-1;$% }$% \fi if(f>\@anim@maxframe||f<0){return -1;}$% a#1_idx=f;$% \if@anim@usrjs if(typeof a#1_usrJS[f]!=='undefined'){$% a#1_curjs=a#1_usrJS[f];$% var ret=\@anim@app\@anim@setTimeout(% execute JS in "parallel" 'try{a#1_curjs();}catch(e){console.\@anim@log(e);}',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 \if@anim@dvisvgm a#1_fr[a#1_on].setAttribute('visibility','hidden');$% a#1_fr[f].setAttribute('visibility','visible');$% \else a#1_fr[a#1_on].state=false;$% a#1_fr[f].state=true;$% \fi a#1_on=f;$% \fi% \if@anim@step\else% \if@anim@meas a#1_frcnt++;$% \fi% \if@anim@pauseframes if(a#1_playing&&a#1_pauseAt[f]){a#1_pause();}$% \fi% \if@anim@chfps if(a#1_nFpsAt[f]!=a#1_fps){a#1_setFps(a#1_nFpsAt[f]);}$% \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 }$% };$% 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 }$% };$% \if@anim@step\else a#1_pause=function(stop){$% try{\@anim@app clearInterval(a#1_int);}catch(e){}$% a#1_playing=false;$% a#1_isPaused=!stop;$% \if@anim@controls@play \if@anim@dvisvgm a#1_btnPauseLeft.setAttribute('visibility','hidden');$% a#1_btnPlayLeft.setAttribute('visibility','visible');$% a#1_btnPauseRight.setAttribute('visibility','hidden');$% a#1_btnPlayRight.setAttribute('visibility','visible');$% \else 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% \fi% };$% a#1_playRight=function(){$% \ifnum\@anim@poster>\z@% if(a#1_posterOn&&!a#1_isPaused){% a#1_seekFrame(0);% a#1_posterOn=false;% }$% \fi% \if@anim@meas a#1_startMeas();\fi var tmp_int;$% try{tmp_int=\@anim@app setInterval('a#1_gotoNext()',% 1000/a#1_fps/a#1_spd);}catch(e){}$% try{\@anim@app clearInterval(a#1_int);}catch(e){}$% a#1_int=tmp_int;$% a#1_playsRight=true;$% a#1_playing=true;$% a#1_isPaused=false;$% \if@anim@controls@play% \if@anim@dvisvgm a#1_btnPauseLeft.setAttribute('visibility','visible');$% a#1_btnPlayLeft.setAttribute('visibility','hidden');$% a#1_btnPauseRight.setAttribute('visibility','visible');$% a#1_btnPlayRight.setAttribute('visibility','hidden');$% \else 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% \fi% };$% a#1_playLeft=function(){$% \ifnum\@anim@poster>\z@% if(a#1_posterOn&&!a#1_isPaused){% a#1_seekFrame(\@anim@maxframe);% a#1_posterOn=false;% }$% \fi% \if@anim@meas a#1_startMeas();\fi var tmp_int;$% try{tmp_int=\@anim@app setInterval('a#1_gotoPrev()',% 1000/a#1_fps/a#1_spd);}catch(e){}$% try{\@anim@app clearInterval(a#1_int);}catch(e){}$% a#1_int=tmp_int;$% a#1_playsRight=false;$% a#1_playing=true;$% a#1_isPaused=false;$% \if@anim@controls@play% \if@anim@dvisvgm a#1_btnPauseLeft.setAttribute('visibility','visible');$% a#1_btnPlayLeft.setAttribute('visibility','hidden');$% a#1_btnPauseRight.setAttribute('visibility','visible');$% a#1_btnPlayRight.setAttribute('visibility','hidden');$% \else 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% \fi% };$% \if@anim@controls@play a#1_playPauseBwd=function(){% if(a#1_playing){a#1_pause();}else{a#1_playBwd();}% };$% a#1_playPauseFwd=function(){% if(a#1_playing){a#1_pause();}else{a#1_playFwd();}% };$% \fi% \if@anim@controls@speed a#1_spdIncr=function(){% speed up animation a#1_spd*=1.1;% a#1_setFps(a#1_fps);% };$% a#1_spdDecr=function(){% slow down animation a#1_spd/=1.1;% a#1_setFps(a#1_fps);% };$% a#1_spdReset=function(){% reset to default speed a#1_spd=1;% a#1_setFps(a#1_fps);% };$% \fi% \if@anim@meas 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();$% \@anim@consoleshow console.\@anim@log(% '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_stopLast();% \if@anim@pauseframes if(a#1_pauseAt[a#1_idx]){a#1_pause();return;}\fi% }% a#1_playLeft();% };$% a#1_playFwd=function(){% if(a#1_idx==\@anim@maxframe){% a#1_stopFirst();% \if@anim@pauseframes if(a#1_pauseAt[a#1_idx]){a#1_pause();return;}\fi% }% a#1_playRight();% };$% \fi% %animation API for labelled anims \ifx\empty\@anim@label\empty\else if(!anim){anim=new Array();}$% if(typeof anim['\@anim@label']==='undefined'){$% anim['\@anim@label']={$% \if@anim@step\else playBwd:a#1_playBwd,$% playFwd:a#1_playFwd,$% pause:a#1_pause,$% get isPlaying(){return a#1_playing;},$% get fps(){return a#1_fps;},$% set fps(f){$% if(f<0||isNaN(f)){% throw new RangeError('Frame_rate_not_in_allowed_range');% }else{a#1_setFps(f);}% },$% get speed(){return a#1_spd;},$% set speed(s){$% if(s<=0||isNaN(s)){$% throw new RangeError('Speed_factor_not_in_allowed_range');$% }else{$% a#1_spd=s;$% a#1_setFps(a#1_fps);$% }$% },$% get dt(){return 1000/a#1_fps/a#1_spd;},$% get playsFwd(){return a#1_playsRight;},$% \fi get numFrames(){return \@anim@frames;},$% get frameNum(){return a#1_idx;},$% set frameNum(ff){$% var f=Math.floor(ff);$% if(f<0||f>\@anim@maxframe||isNaN(f)){% throw new RangeError('Frame_number_not_in_allowed_range');% }$% \if@anim@step if(a#1_seekFrame(f)>-1)a#1_isPaused=true;$% \else if(a#1_playing){$% a#1_pause();a#1_seekFrame(f);$% if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}$% }else{if(a#1_seekFrame(f)>-1)a#1_isPaused=true;}$% \fi% },$% stopFirst:a#1_stopFirst,$% stopLast:a#1_stopLast$% };$% }$% \fi% %poster=none \ifnum\@anim@poster=\@anim@mtwo a#1_seekFrame(-2);$% \fi% %poster=<num>|first \ifnum\@anim@poster>\@anim@mone a#1_seekFrame(\@anim@poster);$% \fi% %poster=last \ifnum\@anim@poster=\@anim@mone a#1_seekFrame(\@anim@maxframe);$% \fi% }% } %page-open/visible code \gdef\@anim@@pojscript#1{% #1: @anim@num \if@anim@step\else% \if@anim@autoplayorresume% \if@anim@autoresume if(a#1_isPaused){$% \fi if(a#1_playsRight){a#1_playFwd();}else{a#1_playBwd();}$% \if@anim@autoresume% }$% \fi% \fi% \fi% } %animation PDF widget's PageOpen/PageVisible code as PDF stream object \gdef\@anim@pojscript#1{% @anim@num \@anim@streamobj{}{% % \@anim@consoleshow% % console.clear();% app.focusRect=false;% \@anim@@jsvardecls{#1}% \@anim@@jsinit{#1}% \@anim@@pojscript{#1}% }% \global\let\@anim@pojscriptobj\@anim@lastobj% } %page-close/invisible code \gdef\@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 \ifnum\@anim@poster=\@anim@mtwo %poster=none if(!a#1_isPaused&&a#1_idx!=-2)a#1_seekFrame(-2);$% not paused == stopped \fi% \ifnum\@anim@poster>\@anim@mone %poster=<num>|first \ifnum\numexpr% \ifnum\@anim@poster>\z@\@ne\else\z@\fi% custom poster *\if@anim@step\z@\else\@ne\fi\relax>\z@% if(!a#1_isPaused){$% if(a#1_idx!=\@anim@poster)a#1_seekFrame(\@anim@poster);$% a#1_posterOn=true;$% }$% \else if(!a#1_isPaused&&a#1_idx!=\@anim@poster)a#1_seekFrame(\@anim@poster);$% \fi% \fi% \ifnum\@anim@poster=\@anim@mone %poster=last if(!a#1_isPaused&&a#1_idx!=\@anim@maxframe)a#1_seekFrame(\@anim@maxframe);$% \fi% } %animation PDF widget's PageClose and PageInvisible code as PDF stream object \gdef\@anim@pcjscript#1{% \@anim@streamobj{}{\@anim@@pcjscript{#1}}% \global\let\@anim@pcjscriptobj\@anim@lastobj% } %other trigger events in the anim widget's AA dictionary \gdef\@anim@wdgtDownJS#1{% \if@anim@step\else % pause on MouseDown try{if(a#1_playing){a#1_pause();}}catch(e){}$% \fi% }% \gdef\@anim@wdgtUpJS#1{% try{$% \if@anim@step% \if@anim@palindrome if(event.\@anim@shift)a#1_playsRight=!a#1_playsRight;$% if(a#1_idx==\@anim@maxframe){% a#1_playsRight=false;% }else if(a#1_idx==0){% a#1_playsRight=true;% }$% if(a#1_playsRight){% a#1_gotoNext();% }else{% a#1_gotoPrev();% }$% \else if(event.\@anim@shift){% if(a#1_idx==0){% a#1_stopLast();% }else{% a#1_gotoPrev();% }$% }else{% if(a#1_idx==\@anim@maxframe){% a#1_stopFirst();% }else{% a#1_gotoNext();% }$% }% \fi a#1_isPaused=true;$% \else if(event.\@anim@shift)a#1_playsRight=!a#1_playsRight;$% \if@anim@palindrome if(a#1_idx==0)a#1_playsRight=true;$% if(a#1_idx==\@anim@maxframe)a#1_playsRight=false;$% if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}% \else var doplay=true;$% if(a#1_idx==\@anim@maxframe&&a#1_playsRight){% a#1_stopFirst();% \if@anim@pauseframes if(a#1_pauseAt[a#1_idx]){a#1_pause();doplay=false;}% \fi% }$% if(a#1_idx==0&&!a#1_playsRight){% a#1_stopLast();% \if@anim@pauseframes if(a#1_pauseAt[a#1_idx]){a#1_pause();doplay=false;}% \fi% }$% if(doplay){% if(a#1_playsRight){a#1_playRight();}else{a#1_playLeft();}% }$% \fi \fi% }catch(e){}$% }% \gdef\@anim@EndLeft{EndLeft}% \gdef\@anim@StepLeft{StepLeft}% \gdef\@anim@PlayPauseLeft{PlayPauseLeft}% \gdef\@anim@PlayLeft{PlayLeft}% \gdef\@anim@PauseLeft{PauseLeft}% \gdef\@anim@PlayPauseRight{PlayPauseRight}% \gdef\@anim@PlayRight{PlayRight}% \gdef\@anim@PauseRight{PauseRight}% \gdef\@anim@StepRight{StepRight}% \gdef\@anim@EndRight{EndRight}% \gdef\@anim@Minus{Minus}% \gdef\@anim@Reset{Reset}% \gdef\@anim@Plus{Plus}% %actions for control buttons \gdef\@anim@btnJS#1#2{% \ifx#2\@anim@EndLeft a#1_stopFirst();% \else% \ifx#2\@anim@StepLeft a#1_stepBwd();% \else% \ifx#2\@anim@PlayPauseLeft a#1_playPauseBwd();% \else% \ifx#2\@anim@PlayPauseRight a#1_playPauseFwd();% \else% \ifx#2\@anim@StepRight a#1_stepFwd();% \else% \ifx#2\@anim@EndRight a#1_stopLast();% \else% \ifx#2\@anim@Minus a#1_spdDecr();% \else% \ifx#2\@anim@Reset a#1_spdReset();% \else% \ifx#2\@anim@Plus a#1_spdIncr();% \fi\fi\fi\fi\fi\fi\fi\fi\fi% } \if@anim@dvisvgm \gdef\@anim@script#1{% #1: anim num \special{dvisvgm:raw $<defs>$% <script type="text/javascript">$% <![CDATA[$% \@anim@@jsvardecls{#1}% variables that are supposed to be global (function(){$% IIFE (self-executing anon. function) to limit scope function onload(){$% \@anim@@jsinit{#1}$% \if@anim@nomouse\else document.getElementById('anm#1').addEventListener('mouseup',% onMouseUpWdgt);$% document.getElementById('anm#1').addEventListener('mousedown',% onMouseDownWdgt);$% document.getElementById('anm#1').addEventListener('touchend',% onTouchEndWdgt);$% \fi% onvisible();$% in case of `autoplay' option }$% function onvisible(){$% \@anim@@pojscript{#1}% }$% function onhidden(){$% \@anim@@pcjscript{#1}% }$% function onVisibilityChange(){$% if(document.hidden){% try{onhidden();}catch(e){}% }else{% try{onvisible();}catch(e){}% }$% }$% document.addEventListener('visibilitychange',onVisibilityChange);$% window.addEventListener('load',onload);$% \if@anim@nomouse\else function onWidgetUpAction(event){$% \@anim@wdgtUpJS{#1}% }$% function onTouchEndWdgt(event){$% event.preventDefault();event.stopPropagation();$% \if@anim@step\else if(a#1_playing){try{a#1_pause();}catch(e){}}else{$% \fi% \@anim@wdgtUpJS{#1}% \if@anim@step\else% }$% \fi% }$% function onMouseDownWdgt(event){$% event.preventDefault();event.stopPropagation();$% \@anim@wdgtDownJS{#1}% }$% function onMouseUpWdgt(event){$% event.preventDefault();event.stopPropagation();$% onWidgetUpAction(event);$% }$% \fi% })();$% end of IIFE ]]>$% </script>$% </defs>% }% } \fi \endgroup \endinput