From 6f9e1680085e7bb4d258f6f8116369d122e196e1 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
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:
+%
+% [<empty> | <number> | for <time>] ["accumulating"]
+%
+% When empty (the default value) the animation repeats forever.
+%
+% When a <number> is provided, the animation will repeat <number>
+% times, which need not be an integer.
+%
+% When a <time> is given, the repeating will stop after this much time.
+%
+% When the optional "accumulating" is specified, the repeat
+% accumulates, otherwise each repeat begins with the original start
+% value.
+%
+% Example:
+%
+% \pgfanimateattribute{fill opacity}{repeats, entry={0s}{1}, entry={6s}{0}}
+% \pgfanimateattribute{fill opacity}{repeats=2, entry={0s}{1}, entry={6s}{0}}
+% \pgfanimateattribute{fill opacity}{repeats=2 accumulating, entry={0s}{1}, entry={6s}{0}}
+% \pgfanimateattribute{fill opacity}{repeats=for 15s, entry={0s}{1}, entry={6s}{0}}
+
+\pgfanimationset{
+  repeats/.code={%
+    \pgfutil@in@{accumulating\pgf@stop}{#1\pgf@stop}%
+    \ifpgfutil@in@%
+      \pgfsysanimkeyaccumulate%
+      \pgfanim@parse@acc#1\pgf@stop%
+    \else%
+      \pgfsysanimkeynoaccumulate%
+      \pgfanim@parse@noacc{#1}%
+    \fi%
+  },
+  repeats/.default=,
+  repeat/.style={repeats={#1}},
+  repeat/.default=,
+}%
+\def\pgfanim@parse@acc#1accumulating\pgf@stop{%
+  \pgfanim@parse@noacc{#1}%
+}%
+\def\pgfanim@parse@noacc#1{%
+  \pgfutil@in@{\pgf@stop for}{\pgf@stop#1}%
+  \ifpgfutil@in@%
+    \pgfanim@parse@for#1\pgf@stop%
+  \else%
+    \def\pgf@temp{#1}%
+    \ifx\pgf@temp\pgfutil@empty%
+      \pgfsysanimkeyrepeatindefinite%
+    \else%
+      \pgfmathparse{#1}%
+      \expandafter\pgfsysanimkeyrepeat\expandafter{\pgfmathresult}%
+    \fi%
+  \fi%
+}%
+\def\pgfanim@parse@for for#1\pgf@stop{\pgfparsetime{#1}\expandafter\pgfsysanimkeyrepeatdur\expandafter{\pgftimeresult}}%
+
+
+
+
+
+% Specifies that an animation should begin or end at a certain time
+% (relative to the current context). The "begin..." options may be
+% used multiple times and their effects accumulate, likewise for the
+% "end..." options.
+%
+% #1 = A time
+%
+% Example:
+%
+% \pgfanimateattribute{fill opacity}{begin=2s, end=2.5s, entry={0s}{1}, entry={1s}{0}}
+
+\pgfanimationset{
+  begin/.code=\pgfparsetime{#1}\expandafter\pgfsysanimkeyoffset\expandafter{\pgftimeresult}{begin},
+  end/.code=\pgfparsetime{#1}\expandafter\pgfsysanimkeyoffset\expandafter{\pgftimeresult}{end},
+}%
+
+
+
+% Specifies that an animation should begin (or end) when a certain
+% event takes place.
+%
+% #1 = A list of key-value pairs.
+%
+% The following keys are allowed:
+%
+% event=some event : The begin / end is triggered by that event. The
+%                    list of allowed events is defined in the SVG
+%                    standard.
+% of=some name     : The event does not refer to the current group,
+%                    but to the object named "some name", which must
+%                    previously have been named \pgfuseid. If some
+%                    name contains a period, the part before the
+%                    period must be the name of the id, the part
+%                    following it the type of the id.
+% key=some key     : The trigger is some key being pressed
+% repeat=number    : The trigger is that an animation has been
+%                    repeated number times.
+% delay=time       : A delay, may be negative.
+%
+% These keys are executed with the path prefix /pgf/animation/events.
+%
+% Some of them are predefined:
+%
+% "click" is a shorthand for "event=click"
+% "focus in" is a shorthand for "event=focusin"
+% "focus out" is a shorthand for "event=focusout"
+% "activate" is a shorthand for "event=activate"
+% "mouse down" is a shorthand for "event=mousedown"
+% "mouse up" is a shorthand for "event=mouseup"
+% "mouse over" is a shorthand for "event=mouseover"
+% "mouse move" is a shorthand for "event=mousemove"
+% "mouse out" is a shorthand for "event=mouseout"
+% "begin" is a shorthand for "event=begin"
+% "end" is a shorthand for "event=end"
+%
+% Example:
+%
+% % Begin after 5s or when clicked:
+% \pgfanimateattribute{fill opacity}{begin=5s, begin on=click, entry={0s}{1}, entry={1s}{0}}
+%
+% % Begin, when an object named "button" is clicked
+% \pgfanimateattribute{fill opacity}{begin on={click, of=button}, entry={0s}{1}, entry={1s}{0}, name=another animation}
+%
+% % Begin 1s after some other animation ends
+% \pgfanimateattribute{fill opacity}{begin on={end, of=another animation, delay=1s}, entry={0s}{1}, entry={1s}{0}}
+
+\pgfanimationset{
+  begin on/.code={\pgfanim@make@event{#1}{begin}},%
+  end on/.code={\pgfanim@make@event{#1}{end}},
+}%
+
+\def\pgfanim@make@event#1#2{%
+  \let\pgfanim@event@event\pgfutil@empty%
+  \let\pgf@anim@id\pgfutil@empty%
+  \let\pgf@anim@type\pgfutil@empty%
+  \let\pgfanim@event@key\pgfutil@empty%
+  \let\pgfanim@event@repeat\pgfutil@empty%
+  \let\pgfanim@event@delay\pgfutil@empty%
+  \pgfkeys{/pgf/animation/events/.cd,#1}%
+  \ifx\pgfanim@event@key\pgfutil@empty%
+    \ifx\pgfanim@event@repeat\pgfutil@empty%
+      \ifx\pgfanim@event@event\pgfutil@empty%
+        \pgferror{No event specified}%
+      \else%
+        \pgfsysanimkeyevent{\pgf@anim@id}{\pgf@anim@type}{\pgfanim@event@event}{\pgfanim@event@delay}{#2}%
+      \fi%
+    \else%
+      \pgfsysanimkeyrepeatevent{\pgf@anim@id}{\pgf@anim@type}{\pgfanim@event@repeat}{\pgfanim@event@delay}{#2}%
+    \fi%
+  \else%
+    \pgfsysanimkeyaccesskey{\pgfanim@event@key}{\pgfanim@event@delay}{#2}%
+  \fi%
+}%
+
+\pgfkeys{/pgf/animation/events/.cd,
+  event/.store in=\pgfanim@event@event,
+  of/.code={%
+    \pgf@anim@decomp{#1}%
+    \pgfidrefprevuse\pgf@anim@id\pgf@anim@id@name%
+    \ifx\pgf@anim@id\pgfutil@empty%
+      \pgferror{Unknown object/node name '\pgf@anim@id@name'. Did you
+        mean 'of next=\pgf@anim@id@name'?}%
+    \fi%
+  },
+  of next/.code={%
+    \pgf@anim@decomp{#1}%
+    \pgfidrefnextuse\pgf@anim@id\pgf@anim@id@name%
+  },
+  of id/.code=\def\pgf@anim@id{#1},
+  key/.store in=\pgfanim@event@key,
+  repeat/.code=\pgfmathparse{#1}\let\pgfanim@event@repeat\pgfmathresult,
+  delay/.code=\pgfparsetime{#1}\let\pgfanim@event@delay\pgftimeresult,
+  click/.style={event=click},
+  focus in/.style={event=focusin},
+  focus out/.style={event=focusout},
+  mouse down/.style={event=mousedown},
+  mouse up/.style={event=mouseup},
+  mouse over/.style={event=mouseover},
+  mouse move/.style={event=mousemove},
+  mouse out/.style={event=mouseout},
+  begin/.style={event=begin},
+  end/.style={event=end},
+}%
+
+
+% Specifies the timeline start for a snapshot
+%
+% #1 = a time
+%
+% Description:
+%
+% What a snapshot is taken of an animation (using \pgfsnapshot), all
+% animations normally start at time 0s. When this key is used, the
+% animation's timeline start is considered to be at moment #1
+% instead.
+
+\pgfanimationset{
+  begin snapshot/.code=
+    \pgfparsetime{#1}\expandafter\pgfsysanimkeysnapshotstart\expandafter{\pgftimeresult}
+}%
+
+
+% Specifies the origin for transforming animations
+%
+% #1 = a pgf point
+%
+% Specifies the origin of transformations (for instance, a rotate will
+% rotate around this point).
+%
+% Example:
+%
+% \pgfanimateattribute{rotate}{entry={0s}{0}, entry={1s}{90}, origin=\pgfpoint{1cm}{1cm}}
+
+\pgfanimationset{
+  origin/.code={%
+    \pgf@process{#1}%
+    \edef\pgf@marshal{%
+      \noexpand\pgfsysanimkeycanvastransform%
+      {\noexpand\pgftransformshift{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}{\noexpand\pgflowlevelsynccm}}%
+      {\noexpand\pgftransforminvert\noexpand\pgflowlevelsynccm}%
+      \noexpand\pgf@anim@save@transform{\noexpand\pgftransformshift{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}%
+    }%
+    \pgf@marshal%
+  },
+}%
+
+\pgfsysanimkeycanvastransform{{\pgflowlevelsynccm}}{\pgftransforminvert\pgflowlevelsynccm}%
+
+
+
+% Specifies the transforming for the animation coordinate system
+%
+% #1 = code that changes the pgf coordinate system
+%
+% Specifies an additional transformation of the coordinate system for
+% animations.
+%
+% Example:
+%
+% \pgfanimateattribute{shift}{entry={0s}{\pgfpointorigin}, entry={1s}{\pgfpoint{1cm}{0cm}}, transform=\pgftransformrotate{30}}
+
+\pgfanimationset{
+  transform/.code={%
+    \pgfsysanimkeycanvastransform{#1{\pgflowlevelsynccm}}{\pgftransforminvert\pgflowlevelsynccm}%
+    \pgf@anim@save@transform{#1}%
+  },
+}%
+
+
+
+% Specifies a motion path.
+%
+% #1 = pgf commands for constructing a path
+%
+% Use this key to specify a motion path for the motion attribute. The
+% values of the "entry" key specify fractions along this path.
+%
+% Example:
+%
+% \pgfanimateattribute{motion}{
+%   entry={0s}{0}, entry={1s}{1},
+%   along=\pgfpathmoveto{\pgfpointorigin} \pgfpathlineto{\pgfpoint{1cm}{1cm}}
+%   }
+
+\pgfanimationset{
+  along/.code=%
+  {%
+    \pgfsyssoftpath@getcurrentpath\pgfanim@save@path%
+    \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
+    #1%
+    \pgfsyssoftpath@getcurrentpath\pgfanim@the@path%
+    \global\let\pgfanim@the@path\pgfanim@the@path%
+    \pgfsyssoftpath@setcurrentpath\pgfanim@save@path%
+  }%
+  \expandafter\pgf@anim@protocol@path@size\pgfanim@the@path\pgf@stop%
+  \expandafter\pgfsysanimkeymovealong\expandafter{\pgfanim@the@path}%
+}%
+
+
+% Specifies a motion soft path.
+%
+% #1 = a pgf soft path (result of calling \pgfsyssoftpath@getcurrentpath)
+%
+% Use this key to specify a motion path for the motion attribute when
+% a softpath has already been constructed.
+%
+% Example:
+%
+% \pgfanimateattribute{motion}{entry={0s}{0}, entry={1s}{1},
+%    along softpath=\pgfsyssoftpath@movetotoken {0pt}{0pt}\pgfsyssoftpath@linetotoken {10pt}{10pt}}
+
+\pgfanimationset{
+  along softpath/.code=%
+  \pgf@anim@protocol@path@size#1\pgf@stop%
+  \pgfsysanimkeymovealong{#1}%
+}%
+
+
+\def\pgf@anim@protocol@path@size{%
+  \pgfutil@ifnextchar\pgf@stop\pgfutil@gobble\pgf@anim@protocol@path@size@%
+}%
+\def\pgf@anim@protocol@path@size@#1#2#3{%
+  \pgf@protocolanimsizes@direct{#2}{#3}%
+  \pgf@anim@protocol@path@size%
+}%
+
+
+% Configures whether the motion is rotated along the path.
+%
+% Example:
+%
+% \pgfanimateattribute{motion}{rotate along, entry={0s}{0}, entry={1s}{1},
+%    along=\pgfpathmoveto{\pgfpointorigin} \pgfpathlineto{\pgfpoint{1cm}{1cm}}}
+
+\pgfanimationset{
+  rotate along/.is choice,
+  rotate along/.default=true,
+  rotate along/true/.code=\pgfsysanimkeyrotatealong,
+  rotate along/false/.code=\pgfsysanimkeynorotatealong,
+}%
+
+
+
+% Specifies an entry
+%
+% #1 = A time. This time will be parsed using \pgfparsetime
+% #2 = A value. The format of this value depends on the current type
+%      of the animation attribute. (So for an animation of the "fill
+%      opacity", #1 must be a scalar value, for an animation of the "fill"
+%      color, #1 must be a color, and so on.)
+%      If #2 is the special text "current value", then the current
+%      value will be used. For SVG, this is allowed only when exactly
+%      two entries are specified and this special value is used for
+%      the first one.
+%
+% Example:
+%
+% \pgfanimateattribute{fill opacity}{entry={0s}{0}, entry={1s}{1}}
+
+\pgfanimationset{entry/.code 2 args=\pgf@anim@entry{#1}{#2}}%
+\def\pgf@anim@entry#1#2{%
+  \pgf@anim@entry@giventrue%
+  \pgfparsetime{#1}%
+  \edef\pgf@marshal{\noexpand\pgfsysanimkeytime{\pgftimeresult}\pgf@anim@entry@spline\pgf@anim@exit@spline}%
+  \pgf@marshal%
+  \def\pgf@temp{#2}%
+  \ifx\pgf@temp\pgf@special@current@text%
+    \pgfsysanimvalcurrent%
+  \else%
+    \pgfanim@type@parser{#2}%
+  \fi%
+}%
+\def\pgf@special@current@text{current value}%
+\newif\ifpgf@anim@entry@given
+
+
+% Specifies a base value
+%
+% #1 = A value. The format is as for the entry key.
+%
+% Description:
+%
+% Will set the "base" value of the animation, which is a value that is
+% used when the animation is not active.
+%
+% Example:
+%
+% \pgfanimateattribute{fill opacity}{base = 0.5, entry={0s}{0.5}, entry={1s}{1}}
+
+\pgfanimationset{base/.code=\pgf@anim@base{#1}}%
+\def\pgf@anim@base#1{%
+  \pgfsysanimkeybase%
+  \pgfanim@type@parser{#1}%
+}%
+
+
+% Specifies that there is an entry "at infinity".
+%
+% When an animation ends, its "effect" can either persist or it can be
+% removed. Setting "freeze at end" to true will cause it to persist,
+% otherwise it will be removed.
+%
+% Example:
+%
+% \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={1s}{0}, freeze at end}
+
+\pgfanimationset{
+  freeze at end/.is choice,
+  freeze at end/.default=true,
+  freeze at end/true/.code=\pgfsysanimkeyfreezeatend,
+  freeze at end/false/.code=\pgfsysanimkeyremoveatend,
+}%
+
+
+
+% Specifies an entry or exit spline control
+%
+% #1 = time fraction
+% #2 = attribute fraction
+%
+% Description:
+%
+% Suppose that an animation is supposed to interpolate a attribute's
+% value between the two values "50" and "100" over a time of 10s. The
+% simplest way of doing so is to do a linear interpolation, where the
+% value as, say, 1s is 55, at 2s it is 60, and so on.
+%
+% Unfortunately, the linear interpolation does not "look" nice in many
+% cases since the acceleration of a linear interpolation is zero
+% during the animation, but infinite at the beginning and at the end;
+% which looks "jerky".
+%
+% To avoid this, you can specify that the time--attribute curve should
+% not be a straight line, but rather a curve. You specify this curve
+% using a spline.
+%
+% The most logical "coordinate rectangle" used for this spline in our
+% example would be (0s,50) and (10s,100) and we would like to specify
+% something like "(0s,50) .. controls (5s,50) and (9s,100)
+% .. (10s,100)". This would result in a time--attribute curve where
+% the attribute at 50 changes slowly at 0s and also arrives slowly at
+% 100 at 10s, but speeds up between these values.
+%
+% We call the first control point (5s,50) the "exit control" and call
+% (9s,100) the "entry control": The first control dictates how quickly
+% or slowly a time point is left, the second dictates how quickly or
+% slowly we enter the next one.
+%
+% The control points are, however, not specified in the coordinate
+% system indicated above. Rather, the rectangle (0s,50) to (10s, 100),
+% gets normalized to (0,0) to (1,1). The control point (5s,50) would
+% thus become (0.5,0) and (9s,100) becomes (0.9,1).
+%
+% Example:
+%
+% \pgfanimateattribute{rotate}{
+%   exit control={0.5}{0},
+%   entry control={0.9}{1},
+%   entry={0s}{50},
+%   entry={10s}{100}}
+
+\pgfanimationset{
+  entry control/.code 2 args={%
+    \pgfmathsetmacro\pgf@temp@t{#1}%
+    \pgfmathsetmacro\pgf@temp@a{#2}%
+    \edef\pgf@anim@entry@spline{{\pgf@temp@t}{\pgf@temp@a}}%
+  },
+  exit control/.code 2 args={%
+    \pgfmathsetmacro\pgf@temp@t{#1}%
+    \pgfmathsetmacro\pgf@temp@a{#2}%
+    \edef\pgf@anim@exit@spline{{\pgf@temp@t}{\pgf@temp@a}}%
+  },
+  stay/.code=\let\pgf@anim@exit@spline\pgfsys@stay@text,%
+  jump/.code=\let\pgf@anim@entry@spline\pgfsys@jump@text,%
+  linear/.style={entry control={1}{1},exit control={0}{0}},
+}%
+\def\pgf@anim@entry@spline@base{{1}{1}}%
+\def\pgf@anim@exit@spline@base{{0}{0}}%
+
+\def\pgf@anim@reset@linear{\let\pgf@anim@entry@spline\pgf@anim@entry@spline@base\let\pgf@anim@exit@spline\pgf@anim@exit@spline@base}%
+\pgf@anim@reset@linear
+
+
+
+% Specifies how much arrow tips should be shortened (as in
+% \pgfsetshortenstart)
+%
+% #1 = an additional shortening distance the path start.
+%
+% Description:
+%
+% Works like \pgfsetshortenstart, only for animated paths.
+
+\pgfanimationset{
+  shorten </.code={%
+    \ifpgf@anim@entry@given%
+      \pgferror{You must specify shorten < prior to the path entries}%
+    \else%
+      \pgfmathsetmacro\pgf@anim@marker@extra@shorten@start{#1}%
+      \edef\pgf@anim@marker@extra@shorten@start{\pgf@anim@marker@extra@shorten@start pt}%
+    \fi%
+  },
+  shorten >/.code={%
+    \ifpgf@anim@entry@given%
+      \pgferror{You must specify shorten < prior to the path entries}%
+    \else%
+      \pgfmathsetmacro\pgf@anim@marker@extra@shorten@end{#1}%
+      \edef\pgf@anim@marker@extra@shorten@end{\pgf@anim@marker@extra@shorten@end pt}%
+    \fi%
+  },
+}%
+\def\pgf@anim@marker@extra@shorten@start{0pt}%
+\def\pgf@anim@marker@extra@shorten@end{0pt}%
+\def\pgf@anim@marker@shorten@start{0pt}%
+\def\pgf@anim@marker@shorten@end{0pt}%
+
+% Specifies the arrow tips used for path animations
+%
+% #1 = an arrow specification of the form <start>-<end> as for the
+%      command \pgfsetarrows
+%
+% Description:
+%
+% Specifies arrow tips that are used in a path animation. Note that in
+% order to set the arrow tips of a path that is animated, you always
+% have to use this command. In particular, you should *not* set arrow
+% tips for the to-be-animated path, but use this key and the base key
+% to install a base path with arrow tips.
+
+\pgfanimationset{
+  arrows/.code={%
+    \ifpgf@anim@entry@given%
+      \pgferror{You must specify animation arrows prior to the path entries}%
+    \else%
+      \pgf@anim@parser@arrows#1\pgf@stop%
+    \fi%
+  },
+}%
+
+\def\pgf@anim@parser@arrows#1-#2\pgf@stop{%
+  \pgf@anim@prepare@arrow@start{#1}%
+  \pgf@anim@prepare@arrow@end{#2}%
+  \expandafter\expandafter\expandafter\pgfsysanimkeytipmarkers\expandafter\expandafter\expandafter{\expandafter\pgf@anim@marker@id@start\expandafter}\expandafter{\pgf@anim@marker@id@end}%
+}%
+
+\def\pgf@anim@prepare@arrow@start#1{%
+  \def\pgf@anim@temp{#1}%
+  \ifx\pgf@anim@temp\pgfutil@empty%
+    \let\pgf@anim@marker@id@start\pgfutil@empty%
+    \def\pgf@anim@marker@shorten@start{0pt}%
+  \else%
+    {%
+      \pgfsetarrowsstart{#1}%
+      \pgf@anim@prep@marker@arrow\pgf@start@tip@sequence\pgf@anim@marker@id\pgf@anim@marker@shorten%
+      \global\let\pgf@anim@marker@id@start\pgf@anim@marker@id%
+      \global\let\pgf@anim@temp\pgf@anim@marker@shorten%
+    }%
+    \let\pgf@anim@marker@shorten@start\pgf@anim@temp%
+  \fi%
+}%
+
+\def\pgf@anim@prepare@arrow@end#1{%
+  \def\pgf@anim@temp{#1}%
+  \ifx\pgf@anim@temp\pgfutil@empty%
+    \let\pgf@anim@marker@id@end\pgfutil@empty%
+    \def\pgf@anim@marker@shorten@end{0pt}%
+  \else%
+    {%
+      \pgfsetarrowsend{#1}%
+      \pgf@anim@prep@marker@arrow\pgf@end@tip@sequence\pgf@anim@marker@id\pgf@anim@marker@shorten%
+      \global\let\pgf@anim@marker@id@end\pgf@anim@marker@id%
+    }%
+    \let\pgf@anim@marker@shorten@end\pgf@anim@marker@shorten%
+  \fi%
+}%
+
+
+% Draw an arrow using markers
+
+\def\pgf@anim@prep@marker@arrow#1#2#3{%
+  % #1 = tip sequence
+  % #2 = macro for storing marker code
+  % #3 = macro for storing shortening length
+  %
+  % First, compute id's:
+  {%
+    \let\pgf@arrow@handle\pgf@anim@marker@id@test%
+    \let\pgf@arrow@handle@dot\relax%?
+    \global\let\pgf@anim@marker@id@list\pgfutil@empty%
+    #1%
+  }%
+  \expandafter\let\expandafter#2\csname pgfanim@marker@cache@\pgf@anim@marker@id@list\endcsname%
+  \expandafter\let\expandafter#3\csname pgfanim@marker@cachel@\pgf@anim@marker@id@list\endcsname%
+  \ifx#2\relax% ok, have to create it!
+    \pgf@relevantforpicturesizefalse%
+    \pgfinterruptpath%
+      \pgf@arrow@compute@shortening{#1}%
+      \xdef#3{\the\pgf@xa}%
+      {%
+        \let\pgf@arrow@handle\pgf@anim@drawer@marker
+        \let\pgf@arrow@handle@dot\relax%
+        \pgfsys@marker@declare#2{%
+          \pgftransformxshift{-\pgf@xb}%
+          \pgftransformxshift{\pgf@xa}%
+          #1%
+        }%
+      }%
+    \endpgfinterruptpath%
+    \expandafter\global\expandafter\let\csname pgfanim@marker@cache@\pgf@anim@marker@id@list\endcsname#2%
+    \expandafter\global\expandafter\let\csname pgfanim@marker@cachel@\pgf@anim@marker@id@list\endcsname#3%
+  \fi%
+}%
+
+\def\pgf@anim@marker@id@test#1#2{%
+  \pgfarrows@getid{#1}{#2}%
+  \expandafter\expandafter\expandafter\pgf@arrow@drawer@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
+  \xdef\pgf@anim@marker@id@list{\pgf@anim@marker@id@list:\pgf@arrow@id\ifpgfarrowswap s\else n\fi\pgfarrows@slant w\the\pgf@xc}%
+}%
+
+\def\pgf@anim@drawer@marker#1#2{%
+  % Prepare:
+  {%
+    \pgfarrows@getid{#1}{#2}%
+    % Do shift:
+    \expandafter\expandafter\expandafter\pgf@arrow@drawer@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
+    % Do slant:
+    \ifdim\pgfarrows@slant pt=0pt%
+    \else%
+      \pgftransformxslant{\pgfarrows@slant}%
+    \fi%
+    % do swap:
+    \ifpgfarrowswap%
+      \pgftransformyscale{-1}%
+    \fi%
+    {%
+      \csname pgf@ar@saves@\pgf@arrow@id\endcsname%
+      \pgfsys@beginscope%
+        \pgf@arrows@color@setup%
+        \pgflowlevelsynccm\csname pgf@ar@cache@\pgf@arrow@id\endcsname%
+      \pgfsys@endscope%
+    }%
+  \expandafter}%
+  % Transform to next tip:
+  \expandafter\pgftransformxshift\expandafter{\the\pgf@xc}%
+}%
+
+
+
+
+
+
+
+
+
+% The parsers
+
+% Parse no value
+%
+% #1 is ignored
+%
+% Example:
+%
+% entry = {0s}{5+6}
+
+\def\pgfanim@parse@type@none#1{%
+  \pgfsysanimvalnone%
+}%
+
+% Parse a scalar
+%
+% #1 is a number parsed using \pgfmathparse
+%
+% Example:
+%
+% entry = {0s}{5+6}
+
+\def\pgfanim@parse@type@scalar#1{%
+  \pgfmathparse{#1}%
+  \expandafter\pgfsysanimvalscalar\expandafter{\pgfmathresult}%
+}%
+
+
+% Parse a dimension
+%
+% #1 is a number parsed using \pgfmathparse
+%
+% Example:
+%
+% entry = {0s}{5cm + 2pt}
+
+\def\pgfanim@parse@type@dimension#1{%
+  \pgfmathparse{#1}%
+  \expandafter\pgfsysanimvaldimension\expandafter{\pgfmathresult pt}%
+}%
+
+
+
+% Parse a mapped text
+%
+% #1 is a text. It is looked up in \pgf@anim@map@#1 and gets replaced
+% by what this macro expands to.
+%
+% Example:
+%
+% entry = {0s}{true}
+
+\def\pgfanim@parse@type@mapped#1{%
+  {%
+    \expandafter\let\expandafter\pgf@temp\csname pgf@anim@map@#1\endcsname\relax%
+    \ifx\pgf@temp\relax%
+      \pgferror{Value '#1' not allowed for an animation for this attribute}%
+      \let\pgf@temp\pgfutil@empty%
+    \fi%
+  \expandafter}%
+  \expandafter\pgfsysanimvaltext\expandafter{\pgf@temp}%
+}%
+
+
+% Parse a color
+%
+% #1 is a color
+%
+% entry = {0s}{blue!20}
+
+\def\pgfanim@parse@type@color#1{%
+  \pgfsysanimvalcolor{#1}%
+}%
+
+
+% Parse a path
+%
+% #1 is a sequence of pgf path construction commands
+%
+% entry = {0s}{\pgfpathmoveto{\pgfpointorigin} \pgfpathlineto{\pgfpoint{1cm}{1cm}}}
+
+\def\pgfanim@parse@type@path#1{%
+  {%
+    \pgfsyssoftpath@getcurrentpath\pgfanim@save@path%
+    \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
+    #1%
+    \pgfsyssoftpath@getcurrentpath\pgfanim@the@path%
+    \pgfprocessround{\pgfanim@the@path}{\pgfanim@the@path}%
+    \global\let\pgfanim@the@path\pgfanim@the@path%
+    \pgfsyssoftpath@setcurrentpath\pgfanim@save@path%
+  }%
+  \expandafter\pgfanim@parse@type@softpath\expandafter{\pgfanim@the@path}%
+}%
+
+
+% Parse a softpath
+%
+% #1 is a sequence of pgf softpath token commands
+%
+% entry = {0s}{\pgfsyssoftpath@movetotoken {0pt}{0pt}\pgfsyssoftpath@linetotoken {10pt}{10pt}}
+
+\def\pgfanim@parse@type@softpath#1{%
+  {%
+    \def\pgf@anim@path{#1}%
+    % Shorten?
+    \pgf@worryfalse%
+    \pgf@xb=\pgf@anim@marker@extra@shorten@start%
+    \advance\pgf@xb by\pgf@anim@marker@shorten@start%
+    \pgf@xc=\pgf@anim@marker@extra@shorten@end%
+    \advance\pgf@xc by\pgf@anim@marker@shorten@end%
+    \ifdim\pgf@xb=0pt\else\pgf@worrytrue\fi%
+    \ifdim\pgf@xc=0pt\else\pgf@worrytrue\fi%
+    \ifpgf@worry%
+      \edef\pgf@path@shortening@distance@end{\the\pgf@xc}%
+      \edef\pgf@path@shortening@distance@start{\the\pgf@xb}%
+      % Yes! Need to shorten.
+      \pgf@anim@shorten@path%
+    \fi%
+  \expandafter}%
+  \expandafter\pgfsysanimvalpath\expandafter{\pgf@anim@path}%
+}%
+
+
+\def\pgf@anim@shorten@path{%
+  \pgf@precise@shorteningfalse%
+  \let\pgf@path@shortening@distance\pgf@path@shortening@distance@end%
+  %
+  % Step 1: Split
+  %
+  \pgfprocesssplitpath{\pgf@anim@path}%
+  \pgfprocesssplitsubpath{\pgfprocessresultpathsuffix}%
+  %
+  % Step 2: extract
+  %
+  \expandafter\pgf@parse@end\pgfprocessresultsubpathsuffix\pgf@stop\pgf@stop\pgf@stop%
+  %
+  % Step 3: prep end
+  %
+  \pgf@prep@end%
+  %
+  % Step 4: shorten end
+  %
+  \ifdim\pgf@path@shortening@distance=0pt\else\pgf@do@shorten@end\fi%
+  %
+  \let\pgf@path@shortening@distance\pgf@path@shortening@distance@start%
+  %
+  % Step 5: extract
+  %
+  \expandafter\pgf@parse@start\pgfprocessresultpathsuffix\pgf@stop\pgf@stop\pgf@stop%
+  %
+  % Step 6: prep start
+  %
+  \pgf@prep@start%
+  %
+  % Step 7: shorten start
+  %
+  \ifdim\pgf@path@shortening@distance=0pt\else\pgf@do@shorten@start\fi%
+  \expandafter\expandafter\expandafter\def%
+  \expandafter\expandafter\expandafter\pgf@anim@path%
+  \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathprefix\pgfprocessresultpathsuffix}%
+}%
+
+
+
+% Parse a point
+%
+% #1 is a point
+%
+% entry = {0s}{\pgfpoint{1cm}{2cm}}
+
+\def\pgfanim@parse@type@point#1{%
+  \pgf@process{#1}%
+  \pgf@protocolanimsizes\pgf@x\pgf@y%
+  \expandafter\expandafter\expandafter\pgfsysanimvaltranslate\expandafter\expandafter\expandafter{\expandafter\the\expandafter\pgf@x\expandafter}\expandafter{\the\pgf@y}%
+}%
+
+
+% Parse a scaling
+%
+% #1 = if #1 contains a comma, the two parts are passed to
+% pgfmathparse, otherwise the whole thing is passed to pgfmathparse.
+%
+% entry = {0s}{2}
+% entry = {0s}{2,1}
+
+\def\pgfanim@parse@type@scaling#1{%
+  \pgfutil@in@{,}{#1}%
+  \ifpgfutil@in@%
+    \pgfanim@unpack@comma#1\pgf@stop%
+  \else%
+    \pgfmathparse{#1}%
+    \expandafter\pgfsysanimvalscale\expandafter{\pgfmathresult}{\pgfmathresult}%
+  \fi%
+}%
+\def\pgfanim@unpack@comma#1,#2\pgf@stop{%
+  \pgfmathsetmacro{\pgf@anim@temp@x}{#1}%
+  \pgfmathsetmacro{\pgf@anim@temp@y}{#2}%
+  \expandafter\expandafter\expandafter\pgfsysanimvalscale\expandafter\expandafter\expandafter{\expandafter\pgf@anim@temp@x\expandafter}\expandafter{\pgf@anim@temp@y}%
+}%
+
+
+
+% Parse a viewbox
+%
+% #1 consists of two points, each in parentheses
+%
+% entry = {0s}{{\pgfpoint{1cm}{2cm}}{\pgfpoint{3cm}{4cm}}}
+
+\def\pgfanim@parse@type@viewbox#1{%
+  {%
+    \pgfanim@unpack@viewbox#1%
+    \xdef\pgf@anim@caller{\noexpand\pgfsysanimvalviewbox{\the\pgf@x}{\the\pgf@y}{\the\pgf@xa}{\the\pgf@ya}}%
+  }%
+  \pgf@anim@caller%
+}%
+\def\pgfanim@unpack@viewbox#1#2{%
+  \pgfpointtransformed{#2}%
+  \pgf@xa\pgf@x%
+  \pgf@ya\pgf@y%
+  \pgfpointtransformed{#1}%
+  \ifdim\pgf@xa<\pgf@x% swap needed
+    \pgf@xb=\pgf@x%
+    \pgf@x=\pgf@xa%
+    \pgf@xa=\pgf@xb%
+  \fi%
+  \ifdim\pgf@ya<\pgf@y% swap needed
+    \pgf@yb=\pgf@y%
+    \pgf@y=\pgf@ya%
+    \pgf@ya=\pgf@yb%
+  \fi%
+}%
+
+
+
+
+% Parse a dash pattern
+%
+% #1,#2 is a dash pattern as in \pgfsetdash
+%
+% entry = {0s}{{{1pt}{2pt}{3pt}{1pt}}{1pt}}
+
+\def\pgfanim@parse@type@dash#1{\pgfanim@parse@type@dash@#1}%
+\def\pgfanim@parse@type@dash@#1#2{%
+  \def\pgf@temp{}%
+  \def\pgf@next{\pgf@strip}%
+  \pgf@strip#1{pgf@stop}%
+  \expandafter\pgfsysanimvaldash\expandafter{\pgf@temp}{#2}%
+}%
+
+
+
+
+
+%
+%
+% Bounding box adjustments in animations.
+%
+%
+
+\def\pgf@protocolanimsizes#1#2{%
+  \edef\pgf@temp{\noexpand\pgf@anim@handle@point{\the#1}{\the#2}}%
+  \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgf@protocolanim@list\expandafter\expandafter\expandafter{\expandafter\pgf@protocolanim@list\pgf@temp}%
+}%
+\def\pgf@protocolanimsizes@direct#1#2{%
+  \expandafter\def\expandafter\pgf@protocolanim@list\expandafter{\pgf@protocolanim@list\pgf@anim@handle@point{#1}{#2}}%
+}%
+\let\pgf@protocolanim@list\pgfutil@empty
+
+\def\pgf@animation@check@translate{%
+  \ifx\pgf@protocolanim@list\pgfutil@empty%
+  \else%
+    \expandafter\expandafter\expandafter\pgf@animation@check@translate@\expandafter\expandafter\expandafter{\expandafter\pgf@protocolanim@list\expandafter}\expandafter{\pgf@anim@saved@transform}%
+  \fi%
+}%
+\let\pgf@animation@check@motion\pgf@animation@check@translate
+
+\def\pgf@animation@check@translate@#1#2{%
+  \pgfsys@attach@to@id\pgf@anim@whom@id\pgf@anim@whom@type{%
+    \pgf@size@hookedtrue%
+    {%
+      % Compute bounding box in local coordinate system
+      #2%
+      \pgf@pt@x0pt%
+      \pgf@pt@y0pt%
+      \pgf@picmaxx=-16000pt\relax%
+      \pgf@picminx=16000pt\relax%
+      \pgf@picmaxy=-16000pt\relax%
+      \pgf@picminy=16000pt\relax%
+      #1%
+      \edef\pgf@temp{{\the\pgf@picminx}{\the\pgf@picminy}{\the\pgf@picmaxx}{\the\pgf@picmaxy}}%
+      \expandafter%
+    }\expandafter%
+    \def\expandafter\pgf@temp\expandafter{\pgf@temp}%
+    \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgf@path@size@hook\expandafter\expandafter\expandafter{%
+      \expandafter\pgf@path@size@hook\expandafter\pgf@anim@bb\pgf@temp}%
+  }{}%
+}%
+\def\pgf@anim@handle@point#1#2{%
+  \pgf@x#1\pgf@y#2%
+  \pgf@pos@transform\pgf@x\pgf@y%
+  \ifdim\pgf@x<\pgf@picminx\pgf@picminx\pgf@x\fi%
+  \ifdim\pgf@x>\pgf@picmaxx\pgf@picmaxx\pgf@x\fi%
+  \ifdim\pgf@y<\pgf@picminy\pgf@picminy\pgf@y\fi%
+  \ifdim\pgf@y>\pgf@picmaxy\pgf@picmaxy\pgf@y\fi%
+}%
+
+\newdimen\pgf@anim@dim
+
+\def\pgf@anim@bb#1#2#3#4{% (#1,#2) lower left, (#3, #4) upper right
+  \pgf@anim@dim\pgf@size@hook@x%
+  \advance\pgf@anim@dim by#1\relax%
+  \ifdim\pgf@anim@dim<\pgf@picminx\global\pgf@picminx\pgf@anim@dim\fi%
+  \pgf@anim@dim\pgf@size@hook@x%
+  \advance\pgf@anim@dim by#3\relax%
+  \ifdim\pgf@anim@dim>\pgf@picmaxx\global\pgf@picmaxx\pgf@anim@dim\fi%
+  \pgf@anim@dim\pgf@size@hook@y%
+  \advance\pgf@anim@dim by#2\relax%
+  \ifdim\pgf@anim@dim<\pgf@picminy\global\pgf@picminy\pgf@anim@dim\fi%
+  \pgf@anim@dim\pgf@size@hook@y%
+  \advance\pgf@anim@dim by#4\relax%
+  \ifdim\pgf@anim@dim>\pgf@picmaxy\global\pgf@picmaxy\pgf@anim@dim\fi%
+}%
+
+\def\pgf@anim@save@transform#1{%
+  \def\pgf@anim@saved@transform{#1}%
+}%
+\let\pgf@anim@saved@transform\pgfutil@empty%
+
+\endinput
-- 
cgit v1.2.3

