From 6f9e1680085e7bb4d258f6f8116369d122e196e1 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 16 Jan 2023 03:03:27 +0000 Subject: CTAN sync 202301160303 --- .../generic/modules/pgfmoduleanimations.code.tex | 1314 ++++++++++++++++++++ 1 file changed, 1314 insertions(+) create mode 100644 graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex (limited to 'graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex') diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex new file mode 100644 index 0000000000..c0a8346811 --- /dev/null +++ b/graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex @@ -0,0 +1,1314 @@ +% Copyright 2019 by Till Tantau +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + +\ProvidesFileRCS{pgfmoduleanimations.code.tex} + + +% We need the animation system abstraction: + +\input pgfsysanimations.code.tex + + +% Animate an attribute over time +% +% #1 = an attribute +% #2 = configuration keys +% +% This command adds animation commands for the attribute given in #1 +% of some future object to the current graphic scope. For instance, +% when #1 is "fill opacity" then the fill opacity of the object will +% change over time. The object to which the command refers is +% specified using a special key in #2. +% +% The keys in #2 specify how the changes occur over time. There are a +% number of keys that have an effect on the animation "as a whole" +% (like "repeats") while the most central key is the entry key. This +% key takes two parameters: a time and a value. It specifies that at +% the given time the attribute should have the specified value. The +% times must be given in ascending order. Between the times given in +% this way, the values of the attribute will be interpolated; you can +% influence the details of how this interpolation is done using +% additional keys. +% +% The keys in #2 are given in key-value syntax and can be given in any +% order, except that the entry keys must be given in order of +% ascending times. +% +% The syntax of the second parameter of the entry key depends on +% #1. Currently, these are: +% +% Attribute Value Type +% --------------------------------------- +% fill opacity scalar +% stroke opacity scalar +% opacity scalar +% visible boolean +% line width dimension +% fill color +% stroke color +% motion motion +% translate point +% scale scaling +% rotate scalar +% xskew scalar +% yskew scalar +% path path +% softpath softpath +% view viewbox +% dash phase dimension +% dash pattern dashpattern +% none any +% +% Example: +% +% \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={2s}{0}} + +\def\pgfanimateattribute#1#2{% + \pgfanimateattributecode{#1}{\pgfkeys{/pgf/animation/.cd,#2}}% +}% + + +% Variant of \pgfanimateattribute +% +% #1 = attribute +% #2 = code +% +% Description: +% +% A version of \pgfanimateattribute where instead of keys #2 you +% provide a code #2 that calls the animation keys itself. + +\def\pgfanimateattributecode#1#2{% + {% + \pgfkeys{/pgf/@animation attributes/.cd,#1}% + #2% + \csname pgf@animation@check@\pgf@animation@attribute\endcsname% + \pgfsysanimate{\pgf@animation@attribute}% + }% +}% + + + +% Create a time snapshot +% +% #1 = a time +% +% Description: +% +% This command should be called in a scope prior to all calls of +% animation commands in that scope. When called, all animations will +% be "intercepted" and, instead of creating the animation code, normal +% code will be generated that shows the state of the animation at the +% specified "moment" #1. Since no animation code is involved, this +% works with all drivers. +% +% The command \pgfsnapshotafter works the same way as \pgfsnapshot, +% only the timing is slightly different: Conceptually, #1 is +% interpreted as "#1+epsilon". For instance, if there are two values +% specified for the time #1, then \pgfsnapshot will use the first +% while \pgfsnapshotafter will use the second. Likewise, when an +% animation ends at time #1, \pgfsnapshot will still us the +% animation's value, while \pgfsnapshotafter will not. +% +% Example: +% +% { +% \pgfsnapshot{1.2s} +% \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={2s}{0}} +% \fill (0,0) rectangle (1,1); +% } + +\def\pgfsnapshot#1{\pgfparsetime{#1}\expandafter\pgfsysanimsnapshot\expandafter{\pgftimeresult}}% +\def\pgfsnapshotafter#1{\pgfparsetime{#1}\expandafter\pgfsysanimsnapshotafter\expandafter{\pgftimeresult}}% + + +% The animation attributes + +\pgfkeys{/pgf/@animation attributes/.cd, + visible/.code=\pgf@animate@attr{visibility}{mapped}\def\pgf@anim@map@true{visible}\def\pgf@anim@map@false{hidden}, + stage/.code=\pgf@animate@attr{visibility}{mapped}\def\pgf@anim@map@true{visible}\def\pgf@anim@map@false{hidden}\pgfsysanimkeybase\pgfsysanimvaltext{hidden}, + opacity/.code=\pgf@animate@attr{opacity}{scalar}, + fill opacity/.code=\pgf@animate@attr{fillopacity}{scalar}, + draw opacity/.code=\pgf@animate@attr{strokeopacity}{scalar}, + stroke opacity/.style=draw opacity, + line width/.code=\pgf@animate@attr{linewidth}{dimension}, + fill/.code=\pgf@animate@attr{fillcolor}{color}, + draw/.code=\pgf@animate@attr{strokecolor}{color}, + color/.code=\pgf@animate@attr{color}{color}, + stroke/.style=draw, + motion/.code=\pgf@animate@attr{motion}{scalar}, + translate/.code=\pgf@animate@attr{translate}{point}, + scale/.code=\pgf@animate@attr{scale}{scaling}, + rotate/.code=\pgf@animate@attr{rotate}{scalar}, + xskew/.code=\pgf@animate@attr{skewx}{scalar}, + yskew/.code=\pgf@animate@attr{skewy}{scalar}, + skew x/.style=xskew, + skew y/.style=yskew, + path/.code=\pgf@animate@attr{path}{path}, + softpath/.code=\pgf@animate@attr{path}{softpath}, + view/.code=\pgf@animate@attr{viewbox}{viewbox}, + dash/.code=\pgf@animate@attr{dash}{dash}, + none/.code=\pgf@animate@attr{none}{none}, +}% + +\def\pgf@animate@attr#1#2{% + \def\pgf@animation@attribute{#1}% + \expandafter\let\expandafter\pgfanim@type@parser\csname pgfanim@parse@type@#2\endcsname% +}% + + + +% The time parser +% +% #1 = a time +% +% This macro parses the time in #1, but adds some support for times: +% +% 1) The postfix operator "s" is added, which has no effect. +% 2) The postfix operator "ms" is added, which divides a number by +% 1000, so "2ms" equals "0.002". +% 3) The postfix operator "min" is added, which multiplies a number by +% 60. +% 4) The postfix operator "h" is added, which multiplies a number by +% 3600. +% 5) The infix operator ":" is redefined, so that it multiplies its +% first argument by 60 and adds the second. This implies that +% "1:20" equals "80" and "01:00:00" equals "3600". +% 6) The parsing of octal numbers is switched off to allow things like +% "01:08" for 68s. + +\def\pgfparsetime#1{% + \begingroup% + \pgfmathdeclareoperator{s}{@seconds}{1}{postfix}{600}% + \pgfmathdeclareoperator{m}{m@encountered}{1}{postfix}{600}% + \pgfmathdeclareoperator{i}{i@encountered}{1}{postfix}{600}% + \pgfmathdeclareoperator{n}{@minutes}{1}{postfix}{600}% + \pgfmathdeclareoperator{h}{@hours}{1}{postfix}{600}% + \pgfmathdeclareoperator{:}{time@colon}{2}{infix}{50}% + \pgfmath@octalparsingfalse% + \pgfmathparse{#1}% + \expandafter\endgroup% + \expandafter\def\expandafter\pgftimeresult\expandafter{\pgfmathresult}% +}% + +\newif\ifpgfanim@m@encountered +\newif\ifpgfanim@i@encountered +\pgfmathdeclarefunction{@seconds}{1}{% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \ifpgfanim@m@encountered% + \divide\pgfmath@x by1000\relax% + \fi% + \global\pgfanim@m@encounteredfalse% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% +\pgfmathdeclarefunction{m@encountered}{1}{% + \global\pgfanim@m@encounteredtrue% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% +\pgfmathdeclarefunction{i@encountered}{1}{% + \ifpgfanim@m@encountered% + \global\pgfanim@m@encounteredfalse% + \global\pgfanim@i@encounteredtrue% + \else% + \pgfmath@error{Unexpected i}{}% + \fi% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% +\pgfmathdeclarefunction{@minutes}{1}{% + \ifpgfanim@i@encountered% + \global\pgfanim@i@encounteredfalse% + \else% + \pgfmath@error{Unexpected n}{}% + \fi% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \pgfmath@x60\pgfmath@x\relax% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% +\pgfmathdeclarefunction{@hours}{1}{% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \pgfmath@x3600\pgfmath@x\relax% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% +\pgfmathdeclarefunction{time@colon}{2}{% + \begingroup% + \pgfmath@x=#1pt\relax% + \pgfmath@x=60\pgfmath@x\relax% + \pgfmath@y=#2pt\relax% + \advance\pgfmath@x by\pgfmath@y% + \pgfmath@returnone\pgfmath@x% + \endgroup% +}% + + + +% Sets general animation attributes +% +% #1 = key-value pairs that are executed for the path /pgf/animation/ + +\def\pgfanimationset{\pgfqkeys{/pgf/animation}}% + + +% Sets the target animation scope that should be animated. +% +% #1 = A name that will be used with an idscope. +% +% Example: +% +% \pgfanimateattribute{fill opacity}{whom=some scope, entry={0s}{1}, entry={1s}{0}} +% \begin{scope}[name=some scope] +% \draw (0,0) -- (1,1); +% \draw (1,0) -- (2,1); +% \end{scope} + +\pgfanimationset{ + whom/.code={% + \pgf@anim@decomp{#1}% + \pgfidrefnextuse\pgf@anim@id\pgf@anim@id@name% + \expandafter\expandafter\expandafter\pgfsysanimkeywhom\expandafter\expandafter\expandafter{\expandafter\pgf@anim@id\expandafter}\expandafter{\pgf@anim@type}% + \let\pgf@anim@whom@id\pgf@anim@id% + \let\pgf@anim@whom@type\pgf@anim@type% + } +}% + +\def\pgf@anim@decomp#1{% + \edef\pgf@temp{#1}% + \expandafter\pgfutil@in@\expandafter.\expandafter{\pgf@temp}% + \ifpgfutil@in@% + \expandafter\pgf@anim@decomp@\pgf@temp\pgf@stop% + \else% + \expandafter\pgf@anim@decomp@\pgf@temp.\pgf@stop% + \fi% +}% +\def\pgf@anim@decomp@#1.#2\pgf@stop{% + \def\pgf@anim@id@name{#1}% + \def\pgf@anim@type{#2}% +}% + + +% Assigns a name to this animation so that it can be used as an event +% id in another animation +% +% #1 = A name +% +% The name "previous" is special and always refers to the most recent +% animation before the animation currently being constructed. +% +% Example: +% +% \pgfanimateattribute{fill opacity}{name=anim 1, entry={0s}{1}, entry={1s}{0}} +% \pgfanimateattribute{fill opacity}{begin on={end,of=anim 1}, entry={0s}{1}, entry={1s}{0}} + +\pgfanimationset{ + name/.code=\pgfuseid{#1}, +}% + + + + +% Configures whether an animation can be restarted +% +% Some animations can restart when certain events take place. This key +% configures this. Setting it to +% +% "true" allows a restart at any time, +% "false" does not allow a restart, +% "when not active" allows a restart only, when the element is not +% active. +% +% Example: +% +% \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={1s}{0}, restart=false} + +\pgfanimationset{ + restart/.is choice, + restart/.default=true, + restart/true/.code=\pgfsysanimkeyrestartalways, + restart/false/.code=\pgfsysanimkeyrestartnever, + restart/never/.code=\pgfsysanimkeyrestartnever, + restart/when not active/.code=\pgfsysanimkeyrestartwhennotactive, +}% + + +% Sets the number times an animation should repeat +% +% #1 = A string of the following form: +% +% [ | | for