You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1314 lines
39 KiB
1314 lines
39 KiB
% Copyright 2015 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\relax\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
|
|
|