summaryrefslogtreecommitdiff
path: root/graphics/pgf/base/tex/generic/modules
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-01-16 03:03:27 +0000
committerNorbert Preining <norbert@preining.info>2023-01-16 03:03:27 +0000
commit6f9e1680085e7bb4d258f6f8116369d122e196e1 (patch)
tree9ac0ecb239240d1d672b188f29c1479de215074b /graphics/pgf/base/tex/generic/modules
parentb8345f39630408bb198e7636381ce4240154ca9b (diff)
CTAN sync 202301160303
Diffstat (limited to 'graphics/pgf/base/tex/generic/modules')
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduleanimations.code.tex1314
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmodulebending.code.tex356
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduledatavisualization.code.tex3216
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduledecorations.code.tex2191
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmodulematrix.code.tex660
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmodulenonlineartransformations.code.tex342
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduleoo.code.tex844
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduleparser.code.tex697
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduleplot.code.tex561
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmoduleshapes.code.tex1334
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmodulesnakes.code.tex369
-rw-r--r--graphics/pgf/base/tex/generic/modules/pgfmodulesorting.code.tex69
12 files changed, 11953 insertions, 0 deletions
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
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmodulebending.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmodulebending.code.tex
new file mode 100644
index 0000000000..d2ffa8b3c5
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmodulebending.code.tex
@@ -0,0 +1,356 @@
+% 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{pgfmodulebending.code.tex}
+
+
+%
+% This file defines commands for drawing bending arrows and lines.
+%
+
+\usepgfmodule{nonlineartransformations}%
+\usepgflibrary{curvilinear}%
+
+
+% Configuration options for arrow tips:
+
+\pgfkeys{
+ /pgf/arrow keys/flex/.code=\pgfarrowsaddtooptions{\pgf@arrows@the@rigidity#1pt\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex},
+ /pgf/arrow keys/flex/.default=1,
+ /pgf/arrow keys/flex'/.code=\pgfarrowsaddtooptions{\pgf@arrows@the@rigidity#1pt\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex@prime},
+ /pgf/arrow keys/flex'/.default=1,
+ /pgf/arrow
+ keys/bend/.code=\pgfarrowsaddtooptions{\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@bend},
+}%
+
+
+\def\pgf@arrow@mode@is@flex{1}%
+\def\pgf@arrow@mode@is@flex@prime{2}%
+\def\pgf@arrow@mode@is@bend{3}%
+
+\newdimen\pgf@arrows@the@rigidity
+
+%
+%
+% Handle the end of a curve
+%
+%
+
+% First, the preparation. This is, essentially, setting up the
+% nonlinear transformation
+
+\def\pgf@prep@curveend{
+ \pgftransformreset%
+ \pgfsetcurvilinearbeziercurve{\pgfpointlastonpath}{\pgfpointsecondlastonpath}{\pgfpointthirdlastonpath}{\pgfpointfourthlastonpath}
+}%
+
+% Second, the shortening.
+
+\def\pgf@do@shorten@curvedend{%
+ \expandafter\expandafter\expandafter\pgf@do@shorten@curvedend@unpack\expandafter\pgfpointfourthlastonpath\pgfpointthirdlastonpath%
+}%
+\def\pgf@do@shorten@curvedend@unpack\pgfqpoint#1#2\pgfqpoint#3#4{%
+ \pgf@process{\pgfcurvilineardistancetotime{\pgf@path@shortening@distance}}%
+ % Compute new curve:
+ \pgfpointcurveattime{\pgf@x}{\pgfpointlastonpath}{\pgfpointsecondlastonpath}{\pgfpointthirdlastonpath}{\pgfpointfourthlastonpath}%
+ % \pgfx/y and \pgf xa/xb already correct. Need to setup remaining vector...
+ \pgf@xb#3%
+ \pgf@yb#4%
+ \pgf@xb\pgf@time@t\pgf@xb%
+ \pgf@yb\pgf@time@t\pgf@yb%
+ \advance\pgf@xb by\pgf@time@s\pgf@xc%
+ \advance\pgf@yb by\pgf@time@s\pgf@yc%
+ \edef\pgfprocessresultsubpathsuffix{%
+ \expandafter\noexpand\pgfsubpathfourthlasttoken{#1}{#2}%
+ \noexpand\pgfsyssoftpath@curvetosupportatoken{\the\pgf@xb}{\the\pgf@yb}%
+ \noexpand\pgfsyssoftpath@curvetosupportbtoken{\the\pgf@xa}{\the\pgf@ya}%
+ \noexpand\pgfsyssoftpath@curvetotoken{\the\pgf@x}{\the\pgf@y}}%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgfprocessresultpathsuffix%
+ \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultsubpathprefix\pgfprocessresultsubpathsuffix}%
+}%
+
+% Third, the drawing
+
+\def\pgf@do@draw@curvedend{%
+ \pgf@do@draw@curved\pgf@end@tip@sequence%
+}%
+
+\def\pgf@do@draw@curved#1{%
+ {%
+ \pgftransformreset%
+ \pgf@xb\pgf@arrow@tip@total@length% xb will keep track of the total length
+ \let\pgf@arrow@handle\pgf@draw@curved%
+ \let\pgf@arrow@handle@dot\relax%
+ #1%
+ }%
+}%
+
+\def\pgf@draw@curved#1#2{%
+ % Prepare:
+ {%
+ \pgfarrows@getid{#1}{#2}%
+ % Do shift:
+ \expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
+ \expandafter\let\expandafter\pgf@arrow@bending@mode\csname pgf@ar@bending@mode@#1\endcsname%
+ \ifx\pgf@arrow@bending@mode\pgfutil@empty\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex\fi%
+ % do swap:
+ {%
+ \csname pgf@ar@saves@\pgf@arrow@id\endcsname%
+ \ifcase\pgf@arrow@flex@mode\relax%
+ \expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname% like flex
+ \or%
+ \expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname%
+ \or%
+ \expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
+ \or%
+ \pgf@arrow@drawer@bend%
+ \fi%
+ % hull points inside the above
+ }%
+ \expandafter}%
+ % Transform to next tip:
+ \expandafter\pgf@xb\the\pgf@xb%
+}%
+\def\pgf@falsetext{false}%
+
+\def\pgf@arrow@drawer@rigid@shift#1#2#3{% tip end, back end, line end, sep
+ % Let xa be the actual back end of the current arrow plus the back end:
+ \advance\pgf@xb by#2%
+ \pgf@xa\pgf@xb%
+ % Update the xb:
+ \pgf@x#1%
+ \advance\pgf@x by\pgfarrowsep%
+ \advance\pgf@xb by-\pgf@x%
+}%
+
+
+\def\pgf@arrow@drawer@bend{%
+ \pgftransformnonlinear{\pgf@arrow@bending@mode{\pgf@x}{\pgf@y}}
+ \pgftransformscale{-1}%
+ \pgftransformxshift{-\pgf@xa}%
+ % Do slant:
+ \ifdim\pgfarrows@slant pt=0pt%
+ \else%
+ \pgftransformxslant{\pgfarrows@slant}%
+ \fi%
+ \ifpgfarrowswap%
+ \pgftransformyscale{-1}%
+ \fi%
+ {%
+ \pgf@relevantforpicturesizefalse%
+ \pgfscope%
+ \pgf@arrows@color@setup%
+ \csname pgf@ar@inst@code@\pgf@arrow@id\endcsname%
+ \endpgfscope%
+ }%
+ \pgf@arrows@bending@hull%
+}%
+
+\def\pgf@arrow@drawer@rigid#1#2#3{% (rigid) start, (rigid) end, dummy
+ % Compute the rigid positions:
+ \pgf@x#1% start
+ \pgf@y#2% flexibility*(end-start) + start
+ \advance\pgf@y by-\pgf@x%
+ \pgf@y\pgf@sys@tonumber\pgf@arrows@the@rigidity\pgf@y%
+ \advance\pgf@y by\pgf@x%
+ % Are they equal?
+ \ifdim\pgf@x=\pgf@y%
+ % Yes, do tangent:
+ \pgf@bending@do@tangent%
+ \else%
+ \pgf@bending@do@flex%
+ \fi%
+ \pgf@xc#1%
+ \pgf@xc-\pgf@xc%
+ \pgftransformxshift{+\pgf@xc}%
+ % Do slant:
+ \ifdim\pgfarrows@slant pt=0pt%
+ \else%
+ \pgftransformxslant{\pgfarrows@slant}%
+ \fi%
+ % do swap:
+ \ifpgfarrowswap%
+ \pgftransformyscale{-1}%
+ \fi%
+ \pgfscope%
+ \pgf@arrows@color@setup%
+ \pgflowlevelsynccm\csname pgf@ar@cache@\pgf@arrow@id\endcsname%
+ \endpgfscope%
+ \pgf@arrows@rigid@hull%
+}%
+
+\def\pgf@bending@do@tangent{%
+ \pgf@xb\pgf@xa%
+ \advance\pgf@xb by-\pgf@x%
+ \pgfcurvilineardistancetotime{\pgf@xb}%
+ \pgf@xb\pgf@x%
+ % Compute points:
+ \ifdim\pgf@xb=0pt%
+ \pgf@bending@possible@degenerate%
+ \else%
+ \pgf@bending@do@tangent@normal%
+ \fi%
+ \pgf@ya-\pgf@y%
+ \pgfsettransformentries%
+ {\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
+ {\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@x}{\pgf@xc}{\pgf@yc}%
+}%
+
+\def\pgf@bending@do@tangent@normal{%
+ \pgfpointcurveattime{\pgf@xb}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}%
+ \pgf@xc\pgf@x% save
+ \pgf@yc\pgf@y% save
+ % compute normal:
+ \advance\pgf@xb by-\pgf@xa%
+ \advance\pgf@yb by-\pgf@ya%
+ \pgf@process{\pgfpointnormalised{\pgf@x=\pgf@xb\pgf@y=\pgf@yb}}
+}%
+
+\def\pgf@bending@possible@degenerate{%
+ \ifx\pgf@curvilinear@line@a\pgf@curvilinear@line@b% degenerate!
+ \ifx\pgf@curvilinear@line@a\pgf@curvilinear@line@c% double degenerate!
+ \let\pgf@ref\pgf@curvilinear@line@d%
+ \else
+ \let\pgf@ref\pgf@curvilinear@line@c%
+ \fi%
+ \pgf@process{\pgf@curvilinear@line@a}%
+ \pgf@xc\pgf@x% save
+ \pgf@yc\pgf@y% save
+ \pgf@process{\pgf@ref}%
+ \advance\pgf@x by-\pgf@xc
+ \advance\pgf@y by-\pgf@yc
+ \pgf@process{\pgfpointnormalised{}}
+ \pgf@x-\pgf@x
+ \pgf@y-\pgf@y
+ \else%
+ \pgf@bending@do@tangent@normal%
+ \fi%
+}%
+
+\def\pgf@bending@do@flex{
+ \pgf@xb\pgf@xa%
+ \pgf@xc\pgf@xa%
+ \advance\pgf@xc by-\pgf@x%
+ \advance\pgf@xb by-\pgf@y%
+ \pgfcurvilineardistancetotime{\pgf@xc}%
+ \pgf@xc\pgf@x%
+ \pgfcurvilineardistancetotime{\pgf@xb}%
+ \pgf@xb\pgf@x%
+ % Compute points:
+ \pgf@process{\pgfpointcurveattime{\pgf@xc}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}}%
+ \pgf@xc\pgf@x\pgf@yc\pgf@y%
+ \pgf@process{\pgfpointcurveattime{\pgf@xb}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}}%
+ \pgf@xb\pgf@x\pgf@yb\pgf@y%
+ \pgftransformarrow{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgfqpoint{\pgf@xc}{\pgf@yc}}%
+}%
+
+
+
+
+
+
+% Convex hull stuff:
+
+\def\pgf@arrows@bending@hull{%
+ \ifpgf@relevantforpicturesize%
+ % Do bb update:
+ \expandafter\let\expandafter\pgf@temp\csname pgf@ar@hull@\pgf@arrow@id\endcsname%
+ \ifx\pgf@temp\pgfutil@empty\else%
+ \let\pgf@arrow@hull@point\pgf@arrow@bending@hull@point@first%
+ \pgf@temp%
+ \pgf@arrow@bending@update@bb%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@arrow@bending@hull@point@first#1#2{%
+ \pgfpointtransformednonlinear{\pgfqpoint{#1}{#2}}%
+ \pgf@xa\pgf@x\pgf@xb\pgf@x%
+ \pgf@ya\pgf@y\pgf@yb\pgf@y%
+ \let\pgf@arrow@hull@point\pgf@arrow@bending@hull@point@other%
+}%
+\def\pgf@arrow@bending@hull@point@other#1#2{%
+ \pgfpointtransformednonlinear{\pgfqpoint{#1}{#2}}%
+ \ifdim\pgf@x<\pgf@xa\pgf@xa\pgf@x\else\ifdim\pgf@x>\pgf@xb\pgf@xb\pgf@x\fi\fi%
+ \ifdim\pgf@y<\pgf@ya\pgf@ya\pgf@y\else\ifdim\pgf@y>\pgf@yb\pgf@yb\pgf@y\fi\fi%
+}%
+
+\def\pgf@arrow@bending@update@bb{%
+ \ifdim\pgf@picmaxx=-16000pt\relax%
+ \global\pgf@picminx\pgf@xa%
+ \global\pgf@picmaxx\pgf@xb%
+ \global\pgf@picminy\pgf@ya%
+ \global\pgf@picmaxy\pgf@yb%
+ \else%
+ \ifdim\pgf@xa<\pgf@picminx\global\pgf@picminx\pgf@xa\fi%
+ \ifdim\pgf@ya<\pgf@picminy\global\pgf@picminy\pgf@ya\fi%
+ \ifdim\pgf@xb>\pgf@picmaxx\global\pgf@picmaxx\pgf@xb\fi%
+ \ifdim\pgf@yb>\pgf@picmaxy\global\pgf@picmaxy\pgf@yb\fi%
+ \fi%
+}%
+
+
+
+
+%
+%
+% Handle the start of a curve
+%
+%
+
+
+% First, the preparation.
+
+\def\pgf@prep@curvedstart{
+ \pgftransformreset%
+ \pgfsetcurvilinearbeziercurve{\pgfpointfirstonpath}{\pgfpointsecondonpath}{\pgfpointthirdonpath}{\pgfpointfourthonpath}%
+}%
+
+% Second, the shortening.
+
+\def\pgf@do@shorten@curvedstart{%
+ \expandafter\expandafter\expandafter\pgf@do@shorten@curvedstart@unpack\expandafter\pgfpointthirdonpath\pgfpointfourthonpath%
+}%
+\def\pgf@do@shorten@curvedstart@unpack\pgfqpoint#1#2\pgfqpoint#3#4{%
+ \pgf@process{\pgfcurvilineardistancetotime{\pgf@path@shortening@distance}}%
+ % Compute new curve:
+ \pgfpointcurveattime{\pgf@x}{\pgfpointfirstonpath}{\pgfpointsecondonpath}{\pgfpointthirdonpath}{\pgfpointfourthonpath}%
+ % \pgfx/y and \pgf xa/xb already correct. Need to setup remaining vector...
+ \pgf@xb#1%
+ \pgf@yb#2%
+ \pgf@xb\pgf@time@t\pgf@xb%
+ \pgf@yb\pgf@time@t\pgf@yb%
+ \advance\pgf@xb by\pgf@time@s\pgf@xc%
+ \advance\pgf@yb by\pgf@time@s\pgf@yc%
+ \edef\pgfpointfirstonpath{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
+ \edef\pgfpointsecondonpath{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
+ \edef\pgfprocessresultpathsuffix{%
+ \noexpand\pgfsyssoftpath@movetotoken{\the\pgf@x}{\the\pgf@y}%
+ \noexpand\pgfsyssoftpath@curvetosupportatoken{\the\pgf@xa}{\the\pgf@ya}%
+ \noexpand\pgfsyssoftpath@curvetosupportbtoken{\the\pgf@xb}{\the\pgf@yb}%
+ \noexpand\pgfsyssoftpath@curvetotoken{#3}{#4}%
+ }
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgfprocessresultpathsuffix%
+ \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathsuffix\pgfsubpathend}%
+}%
+
+
+% Third, the drawing
+
+\def\pgf@do@draw@curvedstart{%
+ \pgf@do@draw@curved\pgf@start@tip@sequence%
+}%
+
+
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduledatavisualization.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduledatavisualization.code.tex
new file mode 100644
index 0000000000..96686aa73f
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduledatavisualization.code.tex
@@ -0,0 +1,3216 @@
+% 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{pgfmoduledatavisualization.code.tex}
+
+\usepgfmodule{oo,shapes}%
+\usepgflibrary{fpu}%
+
+
+% This module defines the basic framework for data visualization.
+
+% In order to visualize data, you first need data. The format for this
+% data is not specified, indeed, different formats are possible. A
+% data point is created each time the command \pgfdatapoint is
+% used. The "parameters" of the data point are just the current values
+% of the keys or macros in the current scope.
+%
+% A set of data points created using the \pgfdata command.
+% When a data point is created, a number of signals are emitted, see
+% the description of \pgfdatapoint. To actually visualize something,
+% objects should be created that listen to these signals and that
+% handle them.
+%
+% The following class manages a data visualization
+
+\pgfooclass{data visualization}
+{%
+ % Class data visualization
+ %
+ % This class is used to "manage" a data visualization. It provides
+ % methods for hooking into the data visualization process and its
+ % constructor initializes the signals that are issued during a data
+ % visualization.
+ %
+ % When a data visualization object is created, a whole bunch of
+ % signal objects. You should then create objects that connect to
+ % these signals. They will be emitted when datapoints come
+ % available.
+ %
+ % It is permissible to have several data visualization objects
+ % active at the same time.
+ %
+ % To use a data visualization object, you should (possibly
+ % repeatedly) call the method add data() or the macro \pgfdata. You should also
+ % create transformation, mapping and visualization objects. Then,
+ % you should, first, call the method survey, which will "survey" the
+ % data, allowing the mapping and bounding objects to compute the
+ % correct ranges. You may then create further objects based on this
+ % data. Then, you should call the "visualize" method, which will
+ % invoke the visualization signals for the data points.
+
+
+ % These attribute store code that should be executed at certain
+ % points. The order is the following:
+ %
+ % 1. "before survey" code
+ % 2. "begin survey" phase signal
+ % 3. "at start survey" code
+ % 4. data points are processed
+ % 5. "at end survey" code
+ % 6. "end survey" phase signal
+ % 7. "after survey" code
+ %
+ % The first seven points will be repeated until the method "do
+ % another survey" is no longer called during a survey.
+ %
+ % 8. "before visualization" code
+ % 9. "begin visualization" phase signal
+ % 10. "at start visualization" code
+ % 11. data points are processed once more
+ % 12. "at end visualization" code
+ % 13. "end visualization" phase signal
+ % 14. "after visualization" code
+ \attribute before survey;%
+ \attribute at start survey;%
+ \attribute at end survey;%
+ \attribute after survey;%
+ \attribute before visualization;%
+ \attribute at start visualization;%
+ \attribute at end visualization;%
+ \attribute after visualization;%
+
+ %
+ % Survey counts and handling
+ %
+
+ \attribute survey count=1;%
+ % Each time a survey is done before the visualization is done, this
+ % count is incremented. Normally, there is only one survey, but
+ % objects may request another survey or even more surveys to be
+ % done, giving them a chance to setup further internal values. By
+ % accessing this count (via the get survey count method), you can
+ % find out which survey is currently being done.
+
+ \attribute number of surveys=1;%
+ % By increasing this count, you can request additional surveys to be
+ % done.
+
+
+ % Stores the to-be-visualized data
+ \attribute data;%
+
+
+ % Stores the signal objects
+ \attribute prepare datapoint signal;%
+ \attribute map datapoint signal;%
+ \attribute transform datapoint signal;%
+ \attribute visualize datapoint signal;%
+ \attribute finish datapoint signal;%
+ \attribute survey datapoint signal;%
+ \attribute phase signal;%
+ \attribute path signal;%
+ \attribute direction signal;%
+ \attribute style signal;%
+
+
+ % Constructor
+ %
+ % Inits the signals
+ \method data visualization() {
+ \pgfoonew{prepare datapoint signal}=new signal()%
+ \pgfoonew{map datapoint signal}=new signal()%
+ \pgfoonew{transform datapoint signal}=new signal()%
+ \pgfoonew{visualize datapoint signal}=new signal()%
+ \pgfoonew{finish datapoint signal}=new signal()%
+ \pgfoonew{survey datapoint signal}=new signal()%
+ \pgfoonew{phase signal}=new signal()%
+ \pgfoonew{path signal}=new signal()%
+ \pgfoonew{direction signal}=new signal()%
+ \pgfoonew{style signal}=new signal()%
+ %
+ % Store this object in a key
+ %
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeyslet{/pgf/data visualization/obj}\pgf@dv@me
+ }%
+
+ % The phase signal will emit the following constants:
+ \def\pgfdvbeforesurvey{1}%
+ \def\pgfdvbeginsurvey{2}%
+ \def\pgfdvendsurvey{3}%
+ \def\pgfdvaftersurvey{4}%
+ \def\pgfdvbeforevisualization{5}%
+ \def\pgfdvbeginvisualization{6}%
+ \def\pgfdvendvisualization{7}%
+ \def\pgfdvaftervisualization{8}%
+
+ % The path signale will meit the following constants:
+ \def\pgfdvpathmovetotoken{5}%
+ \def\pgfdvpathlinetotoken{6}%
+ \def\pgfdvdirectionfromtoken{7}%
+ \def\pgfdvdirectiontotoken{8}%
+ \def\pgfdvdirectionattoken{9}%
+
+ % Method
+ %
+ % Connect the object #1's slot "#2" to the signal named "#3"
+ \method connect(#1,#2,#3) {
+ \pgfoovalueof{#3}.connect(#1,#2)
+ }%
+
+ % Method
+ %
+ % Add data that is to be visualized. The code #1 should call the
+ % \pgfdatapoint macro for each data point it creates.
+ \method add data(#1) {
+ \pgf@dv@stripped@add#1\pgf@stop
+ }%
+ \def\pgf@dv@stripped@add#1\pgf@stop{%
+ \pgfooappend{data}{#1}%
+ }%
+
+
+ % Setters
+ \method before survey(#1) {
+ \pgfooappend{before survey}{#1}
+ }%
+ \method at start survey(#1) {
+ \pgfooappend{at start survey}{#1}
+ }%
+ \method before visualization(#1) {
+ \pgfooappend{before visualization}{#1}
+ }%
+ \method at start visualization(#1) {
+ \pgfooappend{at start visualization}{#1}
+ }%
+
+ % Method
+ \method at end survey(#1) {
+ \pgfooprefix{at end survey}{#1}
+ }%
+ \method after survey(#1) {
+ \pgfooprefix{after survey}{#1}
+ }%
+ \method at end visualization(#1) {
+ \pgfooprefix{at end visualization}{#1}
+ }%
+ \method after visualization(#1) {
+ \pgfooprefix{after visualization}{#1}
+ }%
+
+
+ % Method
+ %
+ % Copy the signals to macros. This is just for efficiency (ha!)
+ \method prepare signal macros() {
+ \pgfooget{prepare datapoint signal}\pgf@signalpreparedatapoint
+ \pgfooget{map datapoint signal}\pgf@signalmapdatapoint
+ \pgfooget{transform datapoint signal}\pgf@signaltransformdatapoint
+ \pgfooget{visualize datapoint signal}\pgf@signalvisualizedatapoint
+ \pgfooget{finish datapoint signal}\pgf@signalfinishdatapoint
+ \pgfooget{survey datapoint signal}\pgf@signalsurveydatapoint
+ \pgfooget{phase signal}\pgf@signalphase
+ \pgfooget{path signal}\pgf@signalpath
+ \pgfooget{direction signal}\pgf@signaldirection
+ \pgfooget{style signal}\pgf@signalstyle
+ }%
+
+
+ % Survey method
+ %
+ % Call this method to "survey" the data. This should be done before
+ % the "visualize" method is called.
+ \method survey() {
+ % Survey phase.
+ \let\pgfdatapoint=\pgfdatapoint@surveyphase%
+ \pgfoothis.prepare signal macros()
+ \pgfooset{survey count}{1}
+ \pgfutil@loop
+ \pgf@signalphase.emit(\pgfdvbeforesurvey)
+ \pgfoovalueof{before survey}%
+ \pgf@signalphase.emit(\pgfdvbeginsurvey)
+ \pgfoovalueof{at start survey}
+ \pgfoovalueof{data}%
+ \pgfoovalueof{at end survey}
+ \pgf@signalphase.emit(\pgfdvendsurvey)%
+ \pgfoovalueof{after survey}
+ \pgf@signalphase.emit(\pgfdvaftersurvey)
+ \c@pgf@counta=\pgfoovalueof{survey count}\relax
+ \c@pgf@countb=\pgfoovalueof{number of surveys}\relax
+ \ifnum\c@pgf@counta<\c@pgf@countb
+ \advance\c@pgf@counta by1\relax
+ \pgfooeset{survey count}{\the\c@pgf@counta}
+ \pgfutil@repeat
+ }%
+
+ % Getter
+ \method get survey count(#1) {
+ \pgfooget{survey count}{#1}
+ }%
+
+ % Request another survey to be done
+ \method do an additional survey() {
+ \c@pgf@counta=\pgfoovalueof{number of surveys}\relax
+ \advance\c@pgf@counta by1\relax
+ \pgfooeset{number of surveys}{\the\c@pgf@counta}
+ }%
+
+ % Visualize method
+ %
+ % This method will cause the actual visualization.
+ \method visualize() {
+ % Visualization phase.
+ \let\pgfdatapoint=\pgfdatapoint@visualizationphase%
+ \pgfoothis.prepare signal macros()
+ \pgf@signalphase.emit(\pgfdvbeforevisualization)%
+ \pgfoovalueof{before visualization}
+ \pgf@signalphase.emit(\pgfdvbeginvisualization)%
+ \pgfoovalueof{at start visualization}
+ \pgfoovalueof{data}%
+ \pgfoovalueof{at end visualization}
+ \pgf@signalphase.emit(\pgfdvendvisualization)%
+ \pgfoovalueof{after visualization}
+ \pgf@signalphase.emit(\pgfdvaftervisualization)%
+ }%
+}%
+
+
+%
+% The data point keys
+%
+% Unlike other keys, the subkeys of /data point/ can simply be set
+% directly. If the key has not been initialized, it will automatically
+% be.
+\pgfkeys{/data point/.unknown/.code={%
+ \pgfkeyssetvalue{/data point/\pgfkeyscurrentname}{#1}
+ },
+}%
+
+
+
+
+% Create and handle a data point
+%
+% Description:
+%
+% This command is called by the survey and the visualize methods
+% whenever a complete data point has been produced. Depending on the
+% current circumstances, different signals will be emitted.
+%
+% The data that is represented by the data point is not given as a
+% parameter. Rather, it is stored in macros and keys, that is, the
+% data point is conceptually given by the settings of all the keys and
+% macros in the local scope.
+%
+% There are two phases to data processing: In the survey phase data
+% points are produced and handled in order to find out things like
+% their number or the minimum and maximum values of attributes, so
+% that axes and picture sizes can be prepared correctly. In the
+% visualization phase, data point are actually shown.
+%
+% During the survey phase, for each data point the signal
+% "surveydatapoint" is emitted.
+%
+% During the visualization phase, more signals are emitted. A prepare
+% signal is emitted first, giving all objects a
+% chance to "prepare" for the data point. Note that it is permissible
+% for an object to manipulate the data point here (and also
+% in later on).
+%
+% Next, the command \pgfdvmapdatapointtocanvas is called. Mainly,
+% the effect of this command is to setup the keys /data point/canvas x
+% and /data point/canvas y, see the description of this command for
+% more details.
+%
+% The next step consists of signaling "visualize data point". Objects
+% listening to this will cause some form of visualization of the
+% data point to occur.
+%
+% Before the visualization is started, it is checked whether the key
+% /data point/name is set (to a non-empty value). If so,
+% a coordinate is created with the given canvas x and y values and
+% this key's value as name.
+%
+% Finally, finish data point allows objects to do any final processing
+% of the data point.
+
+\def\pgfdatapoint@surveyphase{%
+ \pgf@signalpreparedatapoint.emit()%
+ \pgf@signalmapdatapoint.emit()%
+ \pgf@signalsurveydatapoint.emit()%
+}%
+
+\def\pgfdatapoint@visualizationphase{%
+ \pgf@signalpreparedatapoint.emit()%
+ \pgfdvmapdatapointtocanvas%
+ \pgfkeysifdefined{/data point/name}
+ {%
+ \pgfcoordinate{\pgfkeysvalueof{/data point/name}}{\pgfpointdvdatapoint}%
+ }{}%
+ \pgf@signalvisualizedatapoint.emit()%
+ \pgf@signalfinishdatapoint.emit()%
+}%
+
+
+
+% Compute a position of a data point
+%
+% Description:
+%
+% This command uses a special signal to compute the position where a
+% data point should be visualized on the canvas. In detail, the
+% following happens:
+%
+% A local scope is created and the
+% transformation matrix is reset. Then, two signals are emitted: First,
+% "map data points" and then "transform data point". The first
+% lets listening objects "map" the object by setting up
+% attributes of the data point. The second asks objects
+% listening to this signal to transform the current transformation
+% matrix. After the signals, we compute where
+% the origin lies inside this transformed coordinate system. Then the
+% two keys /data point/canvas x and /data point/canvas y are set to
+% the values of this position. The local scope ends (but the settings
+% of the keys persist by a bit of magic), thus restoring the
+% transformation matrix to its original value.
+
+\def\pgfdvmapdatapointtocanvas{%
+ {%
+ \pgfpointdvlocaldatapoint
+ % Smuggle outside group
+ \expandafter%
+ }%
+ \edef\pgf@marshal{%
+ \noexpand\pgfkeyssetvalue{/data point/canvas x}{\the\pgf@x}
+ \noexpand\pgfkeyssetvalue{/data point/canvas y}{\the\pgf@y}
+ }%
+ \pgf@marshal%
+}%
+
+% Help functions for locating a canvas data point
+%
+% Description:
+%
+% The first function returns the data point computed by a
+% canvasposition... call.
+
+\def\pgfpointdvdatapoint{%
+ \pgfqpoint{\pgfkeysvalueof{/data point/canvas x}}{\pgfkeysvalueof{/data point/canvas y}}%
+}%
+
+\def\pgfpointdvlocaldatapoint{%
+ {%
+ % only returns the data point in \pgf@x and \pgf@y, does not set
+ % canvas x and canvas y
+ \pgf@signalmapdatapoint.emit()%
+ \pgftransformreset%
+ \pgf@signaltransformdatapoint.emit()%
+ \pgfpointtransformed{\pgfpointorigin}%
+ }%
+}%
+
+
+
+%
+% Special path constructions commands
+%
+%
+% The following commands are used to construct paths based on
+% datapoints.
+%
+% Normally, all these methods need to do is to compute the current
+% canvas position of the current data point and then do a moveto,
+% lineto or some other operation to this position.
+%
+% However, when the coordinate system is weird, like with polar
+% coordinates or spherical or log-polar coordinate or whatever, a
+% straight line "along an attribute" is no longer a straight line.
+% In this case, two actions can be taken:
+%
+% 1. The problem can be ignored, resulting in a wrong line.
+% 2. Some clever algorithm kicks in an replaces the straight line by
+% the correct replacement.
+%
+% As always, when a computer tries to be clever, things can go
+% wrong... Nevertheless, some support for the second method is
+% given. This works as follows: Objects can register to the data
+% visualization path signal. This signal is emitted every time the
+% lineto or moveto commands are executed. If an object reacts to such
+% a command and handles it, it should set
+% \pgfdvhandledtrue.
+
+\newif\ifpgfdvhandled
+
+\def\pgfdv@generic#1#2#3{%
+ {%
+ \pgfdvhandledfalse%
+ \pgf@signalmapdatapoint.emit()%
+ #1.emit(#2)%
+ \ifpgfdvhandled%
+ \else%
+ \pgf@process{%
+ \pgftransformreset%
+ \pgf@signaltransformdatapoint.emit()%
+ \pgfpointtransformed{\pgfpointorigin}%
+ }%
+ #3{}%
+ \fi%
+ }%
+}%
+
+
+% Handle a moveto
+%
+% This command has no parameters since the target of the moveto is
+% given by the canvas position of the current local data point.
+\def\pgfpathdvmoveto{%
+ \pgfdv@generic{\pgf@signalpath}{\pgfdvpathmovetotoken}{\pgfpathmoveto}
+}%
+
+
+% Handle a lineto
+%
+% This command has no parameters since the target of the moveto is
+% given by the canvas position of the current local data point.
+\def\pgfpathdvlineto{%
+ \pgfdv@generic{\pgf@signalpath}{\pgfdvpathlinetotoken}{\pgfpathlineto}
+}%
+
+
+
+% Compute a normalized vector at the current point pointing along a
+% line from #1 to #2.
+%
+% #1 = code for setting the attributes of the first point
+% #2 = code for setting the attributes of the second point
+%
+% The current point should be a point on a line from #1 to
+% #2. Both points as well as the current point are
+% localized on the canvas and a vector pointing from the first point
+% to the second one is returned. However, for instance in polar
+% coordinates the vector may actually "point along" the angle axis.
+%
+% Internally, this command first sets up the first data point and then
+% emits a "direction" signal with the \pgfdvpathdirectionfromtoken set and
+% then sets up the second point and emits the corresponding
+% ...totoken. Finally, the \pgfdvpathdirectionattoken is emitted.
+%
+
+\def\pgfpointdvdirection#1#2{%
+ {
+ {
+ #1
+ \pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectionfromtoken}{\xdef\pgf@dv@from{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}
+ }
+ {
+ #2
+ \pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectiontotoken}{\xdef\pgf@dv@to{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}
+ }
+ {\pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectionattoken}{%
+ \pgf@process{
+ \pgfpointnormalised{%
+ \pgfpointdiff{\pgf@dv@from}{\pgf@dv@to}
+ }
+ }}}
+ }
+}%
+
+
+
+
+
+%
+%
+% Data parsing and formatting
+%
+%
+
+
+
+% Run the rendering pipeline on a dataset and/or save the dataset.
+%
+% #1 = options with path /pgf/data/
+% #2 = optionally data given inline in curly braces.
+%
+% Description:
+%
+% This command is used to define a data set. For a single data
+% visualization, multiple data sets can be defined, they will
+% accumulate. Data can be in different formats, as specified by the
+% "format" key, and you can define new formats.
+%
+% The settings of the following keys are important:
+%
+% /pgf/data visualization/obj
+% contains a handle to the dv-object
+%
+% /pgf/data/format
+% stores the format (see below)
+%
+% /pgf/data/read from file
+% determines where the data is.
+%
+% /pgf/data/store in group
+% when nonempty, the data is stored here instead of being fed to the
+% rendering pipeline
+%
+% /pgf/data/use group
+% when nonempty, data that has previously been stored here using
+% |define group| is read from here and all other keys are ignored
+%
+% If "read from file" is empty, the data is stored in the argument that
+% follows. Otherwise, the data is read from the specified source file.
+% This data is stored in an internal variable, which is local to the
+% current group.
+%
+% After the group, the key "/pgf/data/continue code" will be
+% executed.
+%
+% When the data is actually used later on (during a survey or a
+% visualization), independently of what source is used, a format
+% handler is started for each data set. This works as follows: first,
+% the handler's startup code is executed. Then for each line of the
+% data file/the data given inline, the line handler function is
+% called. Finally, the data format end handler is called.
+%
+% The format handler's job is to call \pgfdatapoint each time a
+% complete data point has been produced.
+%
+% Example:
+%
+% \pgfoonew \dv=new data visualization()
+% \pgfoonew \obj=new attribute mapper(...)
+% ...
+%
+% \pgfkeys{/pgf/data/.cd,
+% column 1=dax/low,
+% column 2=dax/high,
+% column 3=dax/entry,
+% column 4=dax/exit}
+%
+% \pgfdata[format=space separated columns]
+% {
+% % today
+% 2000 2300 2100 2200
+% 2000 2350 2200 2500
+% 2200 2300 2250 2260
+% 1800 2260 2260 1900
+% 2000 2300 2100 2200
+% }
+%
+% \pgfdata[format=comma separated columns]
+% {
+% % yesterday
+% 2000, 2350, 2200, 2250
+% 2200, 2300, 2250, 2260
+% }
+%
+% \pgfdata[read from file=data.csv,format=comma separated columns]
+%
+% \dv.survey()
+% \dv.visualize()
+
+\def\pgfdata{\pgfutil@ifnextchar[{\pgf@datagroup@data@opt}{\pgf@datagroup@data@opt[]}}%}%
+\def\pgf@datagroup@data@opt[#1]{%
+ % Ok, add one data thing...
+ \begingroup%
+ \pgfkeys{/pgf/data/.cd,/pgf/every data/.try,#1}%
+ \pgfkeysgetvalue{/pgf/data/continue code}\pgf@dv@cont@code%
+ \global\let\pgf@dv@cont@code\pgf@dv@cont@code%
+ \pgfkeysgetvalue{/pgf/data/use group}\pgf@dv@use@group%
+ \ifx\pgf@dv@use@group\pgfutil@empty%
+ \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data(\pgf@do@data{#1})}%
+ \expandafter\pgf@datagroup@data@opt@cont%
+ \else%
+ \expandafter\ifx\csname pgf@dv@group@@\pgf@dv@use@group\endcsname\relax%
+ \pgferror{Undefined data group '\pgf@dv@use@group'}%
+ \else%
+ {%
+ \pgfkeys{/pgf/data/define group/.code=}% no redefinitions during use
+ \csname pgf@dv@group@@\pgf@dv@use@group\endcsname%
+ }%
+ \fi%
+ \endgroup%
+ \expandafter\pgf@dv@cont@code%
+ \fi%
+}%
+\def\pgf@datagroup@data@opt@cont{%
+ \pgfkeysgetvalue{/pgf/data/format}\pgf@dv@format%
+ \expandafter\let\expandafter\pgf@dv@format@catcodes\csname pgfdv@format@\pgf@dv@format @catcodes\endcsname%
+ \ifx\pgf@dv@format@catcodes\relax
+ \pgferror{Unknown data format '\pgf@dv@format'}%
+ \else%
+ \pgfkeysgetvalue{/pgf/data/read from file}\pgf@dv@source%
+ \ifx\pgf@dv@source\pgfutil@empty%
+ \let\pgf@next\pgf@datagroup@grab@inline%
+ \else%
+ \let\pgf@next\pgf@datagroup@grab@external%
+ \fi%
+ \pgf@next%
+}%
+
+\def\pgf@datagroup@grab@inline{%
+ \pgfutil@ifnextchar\bgroup{%
+ \begingroup%
+ \catcode`\^^M=\active%
+ \pgf@dv@format@catcodes%
+ \pgf@datagroup@grab@@inline}%
+ {\pgferror{Opening brace expected}}%
+}%
+\def\pgf@datagroup@grab@external{%
+ \fi%
+ \endgroup%
+ \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data({{{\pgf@datagroup@do@external}}})}%
+ \pgf@dv@cont@code%
+}%
+
+\def\pgf@dv@do@adddata#1{%
+ \pgfkeysgetvalue{/pgf/data/store in group}\pgf@dv@temp%
+ \ifx\pgf@dv@temp\pgfutil@empty%
+ #1%
+ \else%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@dv@group@@\pgf@dv@temp\endcsname{#1}%
+ \fi%
+}%
+
+{\catcode`\^=7 \catcode`\^^M=13
+ \gdef\pgf@datagroup@grab@@inline#1{%
+ \endgroup%
+ \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data({{{\pgf@datagroup@do@inline#1^^M\pgf@@eol}}})}%
+ \fi%
+ \endgroup%
+ \pgf@dv@cont@code%
+ }%
+}%
+\def\pgf@@eol{\pgf@eol}%
+
+\def\pgf@do@data#1#2{%
+ \begingroup%
+ \pgfkeys{/pgf/data/.cd,/pgf/every data/.try,#1}%
+ \pgfkeysgetvalue{/pgf/data/format}\pgf@dv@format%
+ \expandafter\let\expandafter\pgf@dv@format@line\csname pgfdv@format@\pgf@dv@format @line\endcsname%
+ \expandafter\let\expandafter\pgf@dv@format@emptyline\csname pgfdv@format@\pgf@dv@format @empty\endcsname%
+ \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@startup\endcsname%
+ #2%
+ \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@end\endcsname%
+ \endgroup%
+}%
+
+
+%
+% Read external file
+%
+
+\def\pgf@datagroup@do@external{%
+ \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@catcodes\endcsname%
+ \immediate\openin\r@pgf@reada=\pgfkeysvalueof{/pgf/data/read from file} %
+ \ifeof\r@pgf@reada\relax
+ \pgferror{Data file '\pgfkeysvalueof{/pgf/data/read from file}' not found}%
+ \else
+ \pgf@datagroup@readline%
+ \fi
+ \immediate\closein\r@pgf@reada%
+}%
+
+\def\pgf@partext{\par}%
+\def\pgf@datagroup@readline{%
+ \endlinechar=-1 % suppress white space at end; this is local to `\pgfdata`
+ \immediate\read\r@pgf@reada to \pgf@temp%
+ \ifx\pgf@temp\pgf@partext%
+ \pgf@dv@format@emptyline%
+ \else%
+ \ifx\pgf@temp\pgfutil@empty%
+ \pgf@dv@format@emptyline%
+ \else%
+ \expandafter\pgf@dv@format@line\pgf@temp\pgfeol%
+ \fi%
+ \fi%
+ \ifeof\r@pgf@reada\else\expandafter\pgf@datagroup@readline\fi%
+}%
+
+
+%
+% Read inline data
+%
+
+\def\pgf@datagroup@do@inline{%
+ \pgf@dv@handle@line%
+}%
+
+{\catcode`\^=7 \catcode`\^^M=13
+\gdef\pgf@dv@handle@line{%
+ \pgfutil@ifnextchar^^M{\pgf@dv@format@emptyline\expandafter\pgf@dv@handle@line\pgfutil@gobble}%
+ {\pgfutil@ifnextchar\pgf@@eol{\pgfutil@gobble}{\pgf@dv@handle@nonemptyline}}%
+}%
+\gdef\pgf@dv@handle@nonemptyline#1^^M{%
+ \pgf@dv@format@line#1\pgfeol%
+ \pgf@dv@handle@line%
+}%
+}%
+
+\pgfkeys{
+ /pgf/data/data visualization obj/.initial=\undefined,
+ /pgf/data/format/.initial=table,% the default format
+ /pgf/data/read from file/.initial=,
+ /pgf/data/inline/.style={read from file=},
+ /pgf/data/continue code/.initial=,
+ /pgf/data/store in group/.initial=,
+ /pgf/data/new group/.code={\expandafter\global\expandafter\let\csname pgf@dv@group@@#1\endcsname\pgfutil@empty},
+ /pgf/data/use group/.initial=,
+}%
+
+
+
+
+
+
+% Define a data format
+%
+% #1 = format name
+% #2 = catcode code
+% #3 = startup code
+% #4 = line arguments
+% #5 = line code
+% #6 = empty line code
+% #7 = end code
+%
+% Description:
+%
+% This command defines a new data format for data visualization. When
+% a data set is visualized and the format is set to #1, this handler
+% is used to parse the data.
+%
+% In detail, the \pgfdata command will select a source. Before this
+% source is read, #2 will be executed to setup the
+% catcodes. Additionally, each time the data is parsed, #3 will be
+% called. Then, for each nonempty line of the source, the
+% command #5 is executed, where the line will be matched against the
+% argument pattern given in #4. For empty lines, #6 will be executed
+% instead. At the end of the source, #7 will be executed.
+
+\def\pgfdeclaredataformat#1#2#3#4#5#6#7{%
+ \expandafter\def\csname pgfdv@format@#1@catcodes\endcsname{#2}%
+ \expandafter\def\csname pgfdv@format@#1@startup\endcsname{#3}%
+ \expandafter\def\csname pgfdv@format@#1@line\endcsname#4\pgfeol{#5}%
+ \expandafter\def\csname pgfdv@format@#1@empty\endcsname{#6}%
+ \expandafter\def\csname pgfdv@format@#1@end\endcsname{#7}%
+}%
+
+
+
+%
+% Predefined standard formats
+%
+
+% TeX code format
+%
+% Description:
+%
+% The lines of the data set are assumed to contain executable TeX
+% code that will call \pgfdatapoint.
+%
+% Example:
+%
+% \pgfdatavisualizationrender[format=TeX code]
+% \dataset{
+% \pgfkeyssetvalue{/data point/x}{5}
+% \pgfkeyssetvalue{/data point/y}{5}
+% \pgfdatapoint
+% \pgfkeyssetvalue{/data point/x}{6}
+% \pgfkeyssetvalue{/data point/y}{6}
+% \pgfdatapoint
+% }
+
+\pgfdeclaredataformat{TeX code}{}{}{#1}{#1 }{}{}%
+
+
+
+% Key-value lines format
+%
+% Description:
+%
+% The lines of the data set are passed to \pgfkeys with the path set
+% to /data point.
+%
+% Example:
+%
+% \data[format=named] {
+% x=5, y=6, hi=9
+% x=7, y=6, lo=10
+% }
+
+\pgfdeclaredataformat{named}{}{}{#1}{\pgf@dv@parse@named#1,\pgf@stop}{}{}%
+\def\pgf@dv@parse@named{%
+ \pgfutil@ifnextchar\pgf@stop{\pgfdatapoint\pgfutil@gobble}{\pgf@dv@parse@named@}
+}%
+\def\pgf@dv@parse@named@#1=#2,#3\pgf@stop{%
+ \foreach \pgf@dv@temp in {#2} {%
+ \def\pgf@dv@tempb{/data point/#1=}%
+ \expandafter\expandafter\expandafter\pgfkeys%
+ \expandafter\expandafter\expandafter{\expandafter\pgf@dv@tempb\pgf@dv@temp}%
+ \pgf@dv@parse@named#3\pgf@stop%
+ }
+}%
+
+
+
+
+
+% Table format
+%
+% Description:
+%
+% A table consists of a head line, which contains the attribute names
+% of the values that will be found in the following lines. Each line
+% (except for the headline) contains one data point.
+%
+% Inside each line the data points are separated by a separator like a
+% comma or a space or a colon. The separator can be configured using
+% the key /pgf/data/separator (leave the separator empty or set it to
+% \space for a space as separator). The default separator is a comma.
+%
+% Some tables will miss the headline. In this case, using the
+% /pgf/data/headline key you can provide a headline yourself.
+%
+% Example:
+%
+% \data[format=table] {
+% x y
+% 10 5
+% 11 6
+% 6 7
+% }
+%
+% \data[format=table,separator={,}] {
+% x, y
+% 10, 5
+% 11, 6
+% 6, 7
+% }
+%
+% \data[format=table,headline=x y] {
+% 10 5
+% 11 6
+% 6 7
+% }
+
+\pgfdeclaredataformat{table}
+{} % no catcodes
+{
+ \pgfkeysgetvalue{/pgf/data/headline}\pgf@dv@headline
+ \pgfkeysgetvalue{/pgf/data/separator}\pgf@dv@separator
+ \ifx\pgf@dv@separator\pgfutil@empty
+ \let\pgf@dv@separator\space
+ \fi
+ \ifx\pgf@dv@separator\pgf@dv@spacetext
+ \let\pgf@dv@separator\space
+ \fi
+ \expandafter\def\expandafter\pgf@dv@till@separator%
+ \expandafter##\expandafter1\pgf@dv@separator{\pgf@dv@table@handle{##1}}
+ \expandafter\def\expandafter\pgf@dv@till@separator@head%
+ \expandafter##\expandafter1\pgf@dv@separator{\pgf@dv@head@handle{##1}}
+ \ifx\pgf@dv@headline\pgfutil@empty
+ % Ok, read headline from file
+ \pgfdv@firstlinetrue
+ \else
+ % Headline already set
+ \pgfdv@firstlinefalse
+ \expandafter\pgf@dv@parse@headline\expandafter{\pgf@dv@headline}
+ \fi
+}
+{#1} % special line pattern, so read everything
+{
+ \ifpgfdv@firstline
+ \pgfdv@firstlinefalse
+ \pgf@dv@parse@headline{#1}
+ \else
+ {
+ \c@pgf@counta=0\relax% keep track of attribute number
+ \def\pgf@marshal{\pgf@dv@parse@table#1}
+ \expandafter\expandafter\expandafter\pgf@marshal%
+ \expandafter\pgf@dv@separator\expandafter\pgfeol\pgf@dv@separator
+ \pgfdatapoint
+ }
+ \fi
+}
+{}% ignore empty lines
+{}% no special end code
+
+\newif\ifpgfdv@firstline
+
+\pgfkeys{
+ /pgf/data/separator/.initial={,},
+ /pgf/data/headline/.initial=
+}%
+\def\pgf@dv@spacetext{\space}%
+
+\def\pgf@dv@parse@table{%
+ \pgfutil@ifnextchar"% Special, but ignored right now...
+ {\pgferror{csv with quotes not yet implemented}}
+ {\pgf@dv@till@separator}
+}%
+\def\pgf@dv@table@handle#1{%
+ \def\pgf@temp{#1}%
+ \ifx\pgf@temp\pgfeoltext%
+ % Bingo! Stop
+ \let\pgf@next=\relax%
+ \else%
+ \advance\c@pgf@counta by1\relax%
+ \pgfkeysgetvalue{/pgf/data/table/attribute \the\c@pgf@counta}\pgf@dv@target
+ \ifx\pgf@dv@target\relax%
+ \edef\pgf@dv@target{attribute \the\c@pgf@counta}
+ \pgfkeyslet{/pgf/data/table/attribute \the\c@pgf@counta}\pgf@dv@target
+ \fi
+ \pgfkeyssetvalue{/data point/\pgf@dv@target}{#1}
+ \let\pgf@next=\pgf@dv@parse@table%
+ \fi%
+ \pgf@next%
+}%
+
+
+
+\def\pgf@dv@parse@headline#1{
+ \c@pgf@counta=0\relax% keep track of attribute number
+ \def\pgf@marshal{\pgf@dv@doparse@headline#1}
+ \expandafter\expandafter\expandafter\pgf@marshal%
+ \expandafter\pgf@dv@separator\expandafter\pgfeol\pgf@dv@separator
+}%
+
+\def\pgf@dv@doparse@headline{%
+ \pgfutil@ifnextchar"% Special, but ignored right now...
+ {\pgferror{csv with quotes not yet implemented}}
+ {\pgf@dv@till@separator@head}
+}%
+\def\pgf@dv@head@handle#1{%
+ \def\pgf@temp{#1}%
+ \ifx\pgf@temp\pgfeoltext%
+ % Bingo! Stop
+ \let\pgf@next=\relax%
+ \else%
+ \advance\c@pgf@counta by1\relax%
+ \pgfkeyssetvalue{/pgf/data/table/attribute \the\c@pgf@counta}{#1}
+ \let\pgf@next=\pgf@dv@doparse@headline%
+ \fi%
+ \pgf@next%
+}%
+
+\def\pgfeoltext{\pgfeol}%
+
+
+%
+%
+% Micro math kernel for dv
+%
+%
+
+% The idea behind the following methods is to "abstract away" which
+% math engine is used. In the future, something fancy build on luatex
+% might be used, so it would we should not rely directly on the
+% fpu library code.
+%
+% The system works as follows: First, you "enter" a number into the
+% engine. When you do so, it is converted into some internal
+% representation that cannot be accessed any more and is called a
+% "math variable" henceforth. All commands of the
+% math system only work on math variables.
+%
+% In order to "exit" a value stored in a math variable from the
+% engine, some other macros can be used.
+%
+% Operations like addition or multiplication take two math variables
+% and store the result in another math variable.
+
+
+
+% Store a value in a math variable of the math engine
+%
+% #1 = a math variable (a macro name) that is to store the value
+% #2 = an expression describing a number
+%
+%
+% Description:
+%
+% The #2 should be an expression that evaluates to a number. However,
+% due to the way the pgf math engine(s) work, currently, there are
+% several restrictions/the syntax is not as simple as one might
+% hope. Fortunately, the syntax is hopefully compatible with
+% easier-to-use future systems.
+%
+% The syntax is as follows: #2 may be
+%
+% 1. a simple high-precision number. This number is currently directly
+% passed to \pgfmathfloatparsenumber, so typical permissible values
+% are "100" or "10000000000000" or "nan" or "-5.673543345345e9000"
+%
+% 2. a mathematical expression, which *must* be surrounded by
+% parentheses. From a "mathematical" point of view these
+% parentheses are superfluous, but the they are used to help pgf
+% distinguish expressions from high-precision numbers. (If, in the
+% future, expressions may contain high precision numbers, the
+% parentheses will simply be ignored.)
+%
+% The expression is evaluated using \pgfmathparse, which means that
+% TeX-precision is used. This means, for instance, that numbers
+% larger than about 16500 will create error messages.
+%
+% The advantage is that you may say write things like "(5+6)" or
+% "(pi/2)".
+%
+% 3. In case #2 starts with an exclamation mark (indicating an
+% "escape"), everything following the mark is simply evaluated by
+% TeX. The effect of evaluating #2 should be that the math
+% variable "\pgfdvmathvalue" is set to some value. This value will
+% then be transferred to #1.
+%
+% 4. In case #2 is the result of calling \pgfdvmathexitbyserializing, the
+% "serialized" value is restored. The idea is that the serialized
+% will turn its internal representation of a number into something
+% that can be stored as a text somewhere.
+%
+% Currently, "@" at the beginning of #2 is used to indicate that
+% what follows is a serialized version of a math variable.
+%
+% In order to determine which of the above cases is to be used for a
+% variable, the first symbol #2 is checked, *after* the first symbol
+% of #2 has been expanded once (using \expandafter once).
+%
+% Example:
+%
+% \pgfdvmathenter{\mymacro}{20000000000000}
+% \pgfdvmathenter{\mymacro}{(5+pi)}
+% \pgfdvmathenter{\mymacro}{!\pgfdvmathadd{\pgfdvmathvalue}{\a}{\b}}
+%
+% \pgfdvmathenter{\foo}{5}
+% \pgfdvmathexitbyserializing{\somevalue}{\foo}
+% \pgfdvmathenter{\mymacro}{\somevalue}
+
+\def\pgfdvmathenter#1#2{%
+ \expandafter\pgfdvmathenter@check\expandafter#1#2\pgfdvmath@end%
+}%
+\def\pgfdvmathenter@check#1{%
+ \pgfutil@ifnextchar @{\pgfdvmath@internal#1}{%
+ \pgfutil@ifnextchar ({\pgfdvmath@expression#1}{%)
+ \pgfutil@ifnextchar !{\pgfdvmath@execute#1}{\pgfdvmath@normal#1}}}%
+}%
+
+\def\pgfdvmath@internal#1@#2\pgfdvmath@end{%
+ \def#1{#2}%
+}%
+\def\pgfdvmath@expression#1(#2)#3\pgfdvmath@end{%
+ \pgfmathparse{#2}%
+ \pgfmathfloatparsenumber{\pgfmathresult}%
+ \let#1=\pgfmathresult%
+}%
+\def\pgfdvmath@execute#1!#2\pgfdvmath@end{%
+ #2%
+ \let#1=\pgfdvmathvalue%
+}%
+\def\pgfdvmath@normal#1#2\pgfdvmath@end{%
+ \pgfmathfloatparsenumber{#2}%
+ \let#1=\pgfmathresult%
+}%
+
+
+
+% Print a math variable in the math engine using \pgfmathprintnumber
+%
+% #1 = math variable
+%
+% Description:
+%
+% See the description of \pgfmathprintnumber
+%
+% Example:
+%
+% \pgfdvmathenter{\mymacro}{20000000000000}
+% \pgfdvmathexitbyprinting{\mymacro}
+
+\def\pgfdvmathexitbyprinting#1{%
+ \pgfmathprintnumber{#1}%
+}%
+
+
+
+% Exit a math variable as a number in a scientific and portable number
+% format in a macro
+%
+% #1 = macro in which to store the value
+% #2 = math variable
+%
+% Description:
+%
+% You can exit a number using this operation. You can then directly
+% reenter the number using \pgfdvmathenter
+%
+% Example:
+%
+% \pgfdvmathenter{\mynumber}{20000000000000}
+% \pgfdvmathexitbyscientificformat{\mymacro}{\mynumber}
+
+\def\pgfdvmathexitbyscientificformat#1#2{%
+ \edef#1{\pgfmathfloatvalueof#2}%
+}%
+
+
+
+% Exit a math variable as a "serialized" (= string-based)
+% version.
+%
+% #1 = macro in which to store the value
+% #2 = math variable
+%
+% Description:
+%
+% The serialized version can be reentered using
+% \pgfmathenter and is similar to \pgfdvmathexitbyscientificformat,
+% but exiting and entering are (a bit) faster.
+%
+% Example:
+%
+% \pgfdvmathenter{\mynumber}{20000000000000}
+% \pgfdvmathexitbyserializing{\mymacro}{\mynumber}
+
+\def\pgfdvmathexitbyserializing#1#2{%
+ \edef#1{@#2}%
+}%
+
+
+
+
+
+% Operations on two numbers
+%
+% #1 = macro that should store the result of applying the
+% corresponding operation to the following:
+% #2 = entered number
+% #3 = entered number
+%
+% Description:
+%
+% Sets #1 to the result of applying an operation to #2 and #3
+%
+% Example:
+%
+% \pgfdvmathenter{\a}{2000}
+% \pgfdvmathenter{\b}{5+6}
+% \pgfdvmathadd{\c}{\a}{\b}
+
+\def\pgfdvmathadd#1#2#3{%
+ \pgfmathfloatadd{#2}{#3}%
+ \let#1=\pgfmathresult%
+}%
+\def\pgfdvmathsub#1#2#3{%
+ \pgfmathfloatsubtract{#2}{#3}%
+ \let#1=\pgfmathresult%
+}%
+\def\pgfdvmathmul#1#2#3{%
+ \pgfmathfloatmultiply{#2}{#3}%
+ \let#1=\pgfmathresult%
+}%
+\def\pgfdvmathdiv#1#2#3{%
+ \pgfmathfloatdivide{#2}{#3}%
+ \let#1=\pgfmathresult%
+}%
+
+% Multiply by small number
+%
+% #1 = macro that should store the result of applying the
+% corresponding operation to the following:
+% #2 = entered number
+% #3 = fixed point number like 2 or 0.5, but not 10000000000
+%
+% Description:
+%
+% Sets #1 to the result of applying an operation to #2 and #3
+%
+% Example:
+%
+% \pgfdvmathenter{\a}{2000}
+% \pgfdvmathadd{\b}{\a}{0.2}
+% % \b now stores 400
+
+\def\pgfdvmathmulfixed#1#2#3{%
+ \pgfmathfloatmultiplyfixed{#2}{#3}%
+ \let#1=\pgfmathresult%
+}%
+
+
+
+% Log, ln and exponent functions
+%
+% #1 = a math variable
+% #2 = a math variable
+%
+% Description
+%
+% \pgfdvmathln will compute #1 = ln(#2)
+% \pgfdvmathlog will compute #1 = log_{10}(#2)
+% \pgfdvmathexp will compute #1 = exp(#2)
+% \pgfdvmathpowten will compute #1 = 10^{#2}
+
+\def\pgfdvmathln#1#2{%
+ \pgfmathfloatln{#2}%
+ \let#1=\pgfmathresult%
+}%
+
+\def\pgfdvmathlog#1#2{%
+ \pgfmathfloatln{#2}%
+ \pgfmathfloatmultiply{\pgfmathresult}{\pgfdvmathalwaysloge}%
+ \let#1=\pgfmathresult%
+}%
+
+\def\pgfdvmathexp#1#2{%
+ \pgfmathfloatexp{#2}%
+ \let#1=\pgfmathresult%
+}%
+
+\def\pgfdvmathpowten#1#2{%
+ \pgfmathfloattofixed{#2}%
+ \let\pgf@dv@temp=\pgfmathresult%
+ \pgfmathround{\pgf@dv@temp}%
+ \let\pgf@dv@temp@round=\pgfmathresult%
+ \pgf@x=\pgf@dv@temp@round pt%
+ \pgf@x=-\pgf@x%
+ \advance\pgf@x by\pgf@dv@temp pt\relax%
+ \ifdim\pgf@x>0.0002pt%
+ \pgfmathfloatmultiply{#2}{\pgfdvmathalwayslnten}%
+ \pgfmathfloatexp{\pgfmathresult}%
+ \else
+ \ifdim\pgf@x<-0.0002pt%
+ \pgfmathfloatmultiply{#2}{\pgfdvmathalwayslnten}%
+ \pgfmathfloatexp{\pgfmathresult}%
+ \else
+ \pgf@x=\pgf@dv@temp@round sp%
+ \c@pgf@counta=\pgf@x%
+ \pgfmathfloatcreate{1}{1.0}{\the\c@pgf@counta}%
+ \fi
+ \fi
+ \let#1=\pgfmathresult%
+}%
+
+
+% Floor functions
+%
+% #1 = a math variable
+% #2 = a math variable
+%
+% Description
+%
+% Sets #1 to the largest integer less or equal to #2
+
+\def\pgfdvmathfloor#1#2{%
+ \pgfmathifisint{#2}{%
+ \let#1=#2%
+ }{%
+ \pgfmathfloatgetflags#2\c@pgf@counta%
+ \ifcase\c@pgf@counta
+ \let#1=\pgfdvmathalwayszero%
+ \or
+ \pgfmathfloatfloor{#2}%
+ \let#1=\pgfmathresult%
+ \or
+ \pgfmathfloatsubtract{\pgfdvmathalwaysone}{#2}%
+ \pgfmathfloatfloor{\pgfmathresult}%
+ \pgfmathfloatsubtract{\pgfdvmathalwayszero}{\pgfmathresult}%
+ \let#1=\pgfmathresult%
+ \or\let#1=#2%
+ \or\let#1=#2%
+ \or\let#1=#2%
+ \fi%
+ }%
+}%
+
+
+% Advanced unary operations
+%
+% #1 = macro that should store the result of applying the
+% operation to an entered number
+% #2 = the operation (as a string like "ln")
+% #3 = entered number
+%
+% Description:
+%
+% Sets #1 to the result of applying #2 to #3
+%
+% Example:
+%
+% \pgfdvmathenter{\a}{2000}
+% \pgfdvmathunaryop{\b}{ln}{\a}
+
+\def\pgfdvmathunaryop#1#2#3{%
+ \csname pgfmathfloat#2\endcsname{#3}%
+ \let#1=\pgfmathresult%
+}%
+
+
+% Advanced binary operations
+%
+% #1 = macro that should store the result of applying the
+% operation to two entered number
+% #2 = the operation (as a string like "veclen")
+% #3 = first argument (an entered number)
+% #4 = second argument (an entered number)
+%
+% Description:
+%
+% Sets #1 to the result of applying #2 to #3
+%
+% Example:
+%
+% \pgfdvmathenter{\a}{3}
+% \pgfdvmathenter{\b}{4}
+% \pgfdvmathbinop{\c}{veclen}{\a}{\b}
+
+\def\pgfdvmathbinop#1#2#3#4{%
+ \csname pgfmathfloat#2\endcsname{#3}{#4}%
+ \let#1=\pgfmathresult%
+}%
+
+
+
+% Comparing values
+%
+% #1 = first math variable
+% #2 = second math variable
+% #3 = code to-be-executed if #1 < #2
+% #4 = code to-be-executed if #1 >= #2
+%
+%
+% Example:
+%
+% \pgfdvmathenter{\a}{3}
+% \pgfdvmathenter{\b}{4}
+% \pgfdvmathifless{\a}{\b}{yes}{should not happen}
+
+\def\pgfdvmathifless#1#2#3#4{%
+ \pgfmathfloatlessthan{#1}{#2}%
+ \ifpgfmathfloatcomparison#3\else#4\fi%
+}%
+
+
+
+
+%
+%
+% Standard objects for data visualization
+%
+%
+
+
+%
+% Transformers
+%
+
+\pgfooclass{linear transformer}
+{%
+ % Class linear transformer
+ %
+ % This class is a transformer class. It reacts to the transform
+ % datapoint signal. When this signal is raised, it will shift the
+ % coordinate system as follows: If the current value of /data
+ % point/this.attribute is 0, then the system is shifted to the
+ % current value of this.origin. If the current value is 1, the
+ % system is shifted to this.origin + this.unit vector. For other
+ % values of /data point/this.attribuate, the shift is interpolated
+ % between these two values.
+
+
+ \attribute attribute;%
+ % The attribute (/data point/this.attribute) by which
+ % the unit vector is multiplied. If it is empty (which is
+ % different from 0), no transformation is done at all.
+
+ \attribute origin = \pgfpointorigin;%
+ % The shift in case the /data point/this.attribute is 0.
+
+ \attribute unit vector;%
+ % The coordinate system is additionally shifted by this amount
+ % times the current value of /data point/this.attribute.
+
+
+ % Constructor
+ %
+ % #1 = attribute that is being transformed. Example: x
+ % #2 = a vector corresponding to one unit of #1.
+ % Example: \pgfpoint{1cm}{0cm}
+ \method linear transformer(#1,#2) {
+ \pgfooset{attribute}{#1}
+ \pgf@process{#2}
+ \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
+ \pgfoolet{unit vector}\pgf@temp%
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,transform,transform datapoint signal)
+ }%
+
+ % Setter
+ \method set origin(#1) {
+ \pgf@process{#1}
+ \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
+ \pgfoolet{origin}\pgf@temp%
+ }%
+
+ % Slot
+ %
+ % This slot should be connected to the transform datapoint
+ % signal. When this signal is emitted, the coordinate system will be
+ % shifted according to the current value of the attribute.
+ \method transform() {
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}\pgf@dv@val%
+ \ifx\pgf@dv@val\pgfutil@empty%
+ \else%
+ \ifx\pgf@dv@val\relax%
+ \else%
+ \pgfdvmathenter{\pgf@dv@math@var}{\pgf@dv@val}%
+ \pgfdvmathexitbyscientificformat{\pgf@dv@val}{\pgf@dv@math@var}%
+ \pgftransformshift{\pgfoovalueof{origin}}%
+ \pgfmathfloatgetexponent\pgf@dv@math@var\c@pgf@counta%
+ \ifnum\c@pgf@counta<-3\relax%
+ \else%
+ \pgftransformshift{\pgfpointscale{\pgf@dv@val}{\pgfoovalueof{unit vector}}}%
+ \fi%
+ \fi%
+ \fi%
+ }%
+}%
+
+
+%
+% Numerical mapping of attributes to other attributes
+%
+
+\pgfooclass{interval mapper}
+{%
+ % Class interval mapper
+ %
+ % This interval mapper reacts to the map datapoint signal. Its purpose is to
+ % map one attribute to another attribute. For the first attribute,
+ % an intervals is specified.
+ %
+ % In addition to the in interval [a,b] there is also an outinterval
+ % [c,d]. Values in the range [a,b] are linearly mapped to the
+ % range [c,d] and the result is stored in the second attribute.
+ %
+ % For instance, if the first range is [10,20] and the second range
+ % is [0,100], then 10 is mapped to 0, 11 is mapped to 10, 20 is
+ % mapped to 100 and 30 is mapped to 200.
+ %
+ % It is permissible to specify an additional non-linear
+ % transformation function f. In this case, for an input value x the
+ % position of f(x) inside the interval [f(a),f(b)] is determined and
+ % this position is linearly mapped to [c,d].
+ %
+ % For example, if f(x) = log_10 (x) and the first range [a,b] =
+ % [10,1000] and the second range is [1,2], then 10 is mapped to 1,
+ % 100 is mapped to 1.5 (since f(100) = 3 lies in the middle
+ % between f(10) = 2 and f(1000) = 4) and 100000 is mapped to 3.
+
+
+ \attribute in;%
+ % The name of the input attribute. If the value of this attribute
+ % is empty or undefined, no mapping is done.
+ %
+ % The in attribute may have a subkey called .../const. If this key
+ % has a value different from \relax, it will always be used instead
+ % of the in attribute itself. This can be useful to temporarily
+ % set a constant value to a key inside a mapping chain.
+ %
+ % If the subkey /is min or max is set to "min" or "max", the mapping
+ % will always be done to the respective out min or out max values.
+
+ \attribute out;%
+ % The name of the output attribute.
+
+ \attribute trans;%
+ % Stores (more or less) the transformation function.
+
+ \attribute out min;%
+ % Start of the second range (the value of c).
+
+ \attribute out min;%
+ % End of the second range (the value of d).
+
+ \attribute trans in min;%
+ % Transformed value of the start of the first range (the value
+ % f(a)).
+
+ \attribute scale;%
+ % The scaling factor, that is, the value of (f(b)-f(a))/(d-c).
+
+
+ % Constructor
+ %
+ % #1 = input attribute. Example: velocity.
+ % #2 = output attribute. Example: x
+ % #3 = optional transformation function. The input value for this
+ % function is stored in entered number \pgfvalue.
+ % The output of the function should be stored in the
+ % same entered number.
+ %
+ % The intervals are set using setter methods later on.
+ %
+ \method interval mapper(#1,#2,#3) {
+ \pgfooset{in}{#1}
+ \pgfooset{out}{#2}
+ \def\pgf@temp{#3}%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \pgfooset{trans}{%
+ #3%
+ }%
+ \fi%
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,map,map datapoint signal)
+ }%
+
+ % Method
+ %
+ % #1 = in interval minimum
+ % #2 = in interval maximum
+ % #3 = out interval minimum
+ % #4 = out interval maximum
+ %
+ % This method will (re)compute the correct mappings for the interval
+ % mapper.
+ \method set interval values(#1,#2,#3,#4) {
+ {%
+ \pgfdvmathenter{\pgf@in@interval@min}{#1}
+ \pgfdvmathenter{\pgf@in@interval@max}{#2}
+ \pgfdvmathenter{\pgf@out@interval@min}{#3}
+ \pgfdvmathenter{\pgf@out@interval@max}{#4}
+ % Let's start with the output, it's easier...
+ \pgfoolet{out min}{\pgf@out@interval@min}
+ \pgfoolet{out max}{\pgf@out@interval@max}
+ \pgfdvmathifless{\pgf@in@interval@min}{\pgf@in@interval@max}{%
+ \pgfdvmathsub{\pgf@out@diff}{\pgf@out@interval@max}{\pgf@out@interval@min}
+ \let\pgfvalue=\pgf@in@interval@min
+ \pgfoovalueof{trans}
+ \let\pgf@in@interval@min@transformed=\pgfvalue
+ \pgfoolet{trans in min}{\pgf@in@interval@min@transformed}%
+ \let\pgfvalue=\pgf@in@interval@max
+ \pgfoovalueof{trans}
+ \let\pgf@in@interval@max@transformed=\pgfvalue
+ \pgfdvmathsub{\pgf@diff@in@transformed}{\pgf@in@interval@max@transformed}{\pgf@in@interval@min@transformed}
+ %
+ % Precompute the scaling
+ %
+ \pgfdvmathdiv{\pgf@scale}{\pgf@out@diff}{\pgf@diff@in@transformed}%
+ \pgfoolet{scale}{\pgf@scale}%
+ }{%
+ \pgfoolet{scale}\pgf@dv@no@scale%
+ }%
+ }%
+ }%
+ \def\pgf@dv@no@scale{noscale}%
+
+ % Slot
+ \method map() {
+ \pgfooget{scale}\pgf@dv@scale
+ \ifx\pgf@dv@scale\pgfutil@empty%
+ % not yet setup
+ \else%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/is min or max}\pgf@dv@is%
+ \ifx\pgf@dv@is\pgf@min@text%
+ \pgf@dv@set@out@min%
+ \else%
+ \ifx\pgf@dv@is\pgf@max@text%
+ \pgf@dv@set@out@max%
+ \else%
+ \ifx\pgf@dv@scale\pgf@dv@no@scale%
+ \pgf@dv@mapper@goto@mid%
+ \else%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/const}\pgf@dv@external@value%
+ \ifx\pgf@dv@external@value\relax%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{in}}\pgf@dv@external@value%
+ \fi%
+ \ifx\pgf@dv@external@value\pgfutil@empty%
+ \pgf@dv@mapper@pos@check%
+ \else%
+ \ifx\pgf@dv@external@value\relax%
+ \pgf@dv@mapper@pos@check%
+ \else%
+ \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}%
+ \pgf@dv@mapper@trans
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ }%
+
+ \def\pgf@dv@set@out@min{%
+ \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@min@text%
+ \pgfooget{out min}{\pgf@minmax@temp}%
+ \pgf@dv@set@out@now%
+ }%
+ \def\pgf@dv@set@out@max{%
+ \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@max@text%
+ \pgfooget{out max}{\pgf@minmax@temp}%
+ \pgf@dv@set@out@now%
+ }%
+ \def\pgf@dv@set@out@now{%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset%
+ \ifx\pgf@dv@external@offset\relax\else%
+ \ifx\pgf@dv@external@offset\pgfutil@empty\else%
+ \pgfdvmathenter{\pgfvalue}{\pgf@minmax@temp}%
+ \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}%
+ \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@offset}
+ \pgfdvmathexitbyserializing{\pgf@minmax@temp}{\pgfvalue}%
+ \fi
+ \fi
+ \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@minmax@temp%
+ }%
+
+ \def\pgf@dv@mapper@trans{
+ \pgfooget{trans in min}{\pgf@dv@trans@in@min}%
+ \pgfooget{scale}{\pgf@dv@scale}%
+ \pgfooget{out min}{\pgf@dv@out@min}%
+ \pgfoovalueof{trans}%
+ \pgfdvmathsub{\pgfvalue}{\pgfvalue}{\pgf@dv@trans@in@min}%
+ \pgfdvmathmul{\pgfvalue}{\pgfvalue}{\pgf@dv@scale}%
+ \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@out@min}%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset%
+ \ifx\pgf@dv@external@offset\relax\else%
+ \ifx\pgf@dv@external@offset\pgfutil@empty\else%
+ \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}%
+ \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@offset}
+ \fi
+ \fi
+ \pgfdvmathexitbyserializing{\pgf@temp}{\pgfvalue}%
+ \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
+ }%
+
+ \def\pgf@dv@mapper@pos@check{%
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/out pos}\pgf@dv@pos@value%
+ \ifx\pgf@dv@pos@value\relax\else\if\pgf@dv@pos@value\pgfutil@empty\else%
+ \pgfmathsetmacro{\pgf@dv@pos@num}{\pgf@dv@pos@value}%
+ \pgfmathsetmacro{\pgf@dv@pos@num@prime}{1-\pgf@dv@pos@num}%
+ % Ok, compute transformed min position:
+ \pgfooget{out min}{\pgf@out@interval@min}
+ \pgfooget{out max}{\pgf@out@interval@max}
+ \pgfdvmathmulfixed{\pgf@out@interval@min}{\pgf@out@interval@min}{\pgf@dv@pos@num@prime}
+ \pgfdvmathmulfixed{\pgf@out@interval@max}{\pgf@out@interval@max}{\pgf@dv@pos@num}
+ \pgfdvmathadd{\pgf@out@val}{\pgf@out@interval@min}{\pgf@out@interval@max}%
+ \pgfdvmathexitbyserializing{\pgf@temp}{\pgf@out@val}%
+ \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
+ \fi\fi%
+ }%
+
+ \def\pgf@dv@mapper@goto@mid{%
+ % Ok, compute transformed min position:
+ \pgfooget{out min}{\pgf@out@interval@min}
+ \pgfooget{out max}{\pgf@out@interval@max}
+ \pgfdvmathmulfixed{\pgf@out@interval@min}{\pgf@out@interval@min}{.5}
+ \pgfdvmathmulfixed{\pgf@out@interval@max}{\pgf@out@interval@max}{.5}
+ \pgfdvmathadd{\pgf@out@val}{\pgf@out@interval@min}{\pgf@out@interval@max}%
+ \pgfdvmathexitbyserializing{\pgf@temp}{\pgf@out@val}%
+ \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
+ }%
+}%
+
+
+
+
+
+%\newif\ifpgf@dvclip
+\newif\ifpgf@dvignore
+
+\pgfooclass{scaling mapper}
+{%
+ % Class scaling mapper
+ %
+ % A scaling mapper is (mainly) used to scale an attribute in such a way
+ % that it can be rendered easily on a page. The idea is that you
+ % specify some attribute and a desired target interval size (like
+ % [0,5]). The scaling mapper will then survey the data and will setup a
+ % interval mapper in such a way that the minimum value present in the data is
+ % mapped to 0 and the maximum to 5. However, it is also possible to,
+ % say, only have the maximum value mapped to 5 and have 0 be mapped
+ % to 0. Other, more complicated specifications are also possible.
+ %
+ % The scaling mapper internally creates several objects: First, a surveyor
+ % for determining the minimum and maximum values of the attribute
+ % and a interval mapper for then mapping the values to the scaled
+ % values. Additionally, interval objects are needed.
+
+ \attribute in;%
+ % The to-be-scaled attribute;
+
+ \attribute out;%
+ % The attribute storing the scaled value.
+
+ \attribute in range obj;%
+ % This interval keep track of the range of the in attribute
+
+ \attribute scaling spec;%
+ % A specification of how the scaling should be performed.
+ %
+ % The format is the following:
+ %
+ % #1 at #2 and #3 at #4
+ %
+ % Here, #2 and #4 must be numbers. #1 and #3 can either be numbers
+ % or #1 can be the text "min" and #3 can be the text "max".
+ %
+ % The effect of such a specification is the following: The value #1
+ % is mapped to #2, the value #3 is mapped to #4 and values between
+ % #1 and #3 (or outside this range) are mapped linearly to a value
+ % between (or outside) #2 and #4. In case #1 is set to "min", the
+ % smallest observed value of the in-attribute is mapped to #3 and
+ % similarly for a value of "max" for #3.
+ %
+ % Additionally, as for a interval mapper, a function f might be specified
+ % that deforms the linear mapping. In case f is specified,
+ % f(#1) is mapped to #2 and f(#3) is mapped to #4.
+
+ \attribute spec maps min;%
+ % When the scaling spec maps "min" to some value, rather than some
+ % specific value to that value, then spec maps min will be set to
+ % \pgfutil@firstoftwo, otherwise to \pgfutil@secondoftwo
+
+ \attribute spec maps max;%
+ % Like spec maps min
+
+ \attribute function;%
+ % Stores the function
+
+ \attribute interval mapper;%
+ % Stores the interval mapper object
+
+ \attribute range surveyor;%
+ % Stores the range surveyor object
+
+
+ % Constructor
+ %
+ % #1 = in attribute
+ % #2 = out attribute
+ % #3 = scaling specification
+ % #4 = optional function
+ %
+ \method scaling mapper(#1,#2,#3,#4) {
+ %
+ % Save the parameters in attributes
+ %
+ \pgfooset{in}{#1}
+ \pgfooset{out}{#2}
+ \pgfooset{scaling spec}{#3}
+ \pgfooset{function}{#4}
+ %
+ % Now setup the objects for the before survey phase
+ %
+ %
+ % First, the in range interval
+ \pgfoonew \pgf@dv@in@range@obj=new interval(,)
+ \pgfoolet{in range obj}\pgf@dv@in@range@obj
+ % Second, the in range surveyor. We do not need to store this
+ % object, it will "do its work in the background"
+ \pgfoonew \pgf@dv@range@obj=new range surveyor(#1,\pgf@dv@in@range@obj)
+ \pgf@dv@range@obj.default connects()
+ \pgfoolet{range surveyor}\pgf@dv@range@obj
+ %
+ %
+ % The interval mapper:
+ %
+ \pgfoonew{interval mapper}=new interval mapper(#1,#2,#4)
+ \pgfoovalueof{interval mapper}.default connects()
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Getter
+ %
+ % Returns an interval object that stores the range of the in
+ % attribute.
+ \method get in range interval() {
+ \pgfooget{in range obj}\pgfdvinrangeinterval
+ }%
+
+
+ % Getter
+ %
+ % Returns the out attribute.
+ %
+ \method get out() {
+ \pgfooget{out}\pgfdvout
+ }%
+
+ % Getter
+ %
+ % Returns the function attribute.
+ %
+ \method get function(#1) {
+ \pgfooget{function}#1
+ }%
+
+ % Method
+ %
+ % #1 = a included in value
+ %
+ % This method only affects the survey. The value #1 is recorded as
+ % if it were encountered for the in attribute at some point.
+ %
+ \method include in value(#1) {
+ \pgfoovalueof{range surveyor}.include attribute value({#1})
+ }%
+
+
+ % Method
+ %
+ % #1 = value for the attribute
+ %
+ % Sets the attribute to the (evaluated) given value (evaluation
+ % using \pgfmathparse). When the value is evaluated, the values of
+ % \pgfdvmin and \pgfdvmax will be set to the minimum and maximum
+ % values of the in interval. (See \pgfdvmathenter with the "!"-notation).
+ %
+ % In case #1 is set to the special value "min", it evaluates to
+ % \pgfdvmin, when set to "max" it evaluates to \pgfdvmax.
+ %
+ \method set in to(#1) {%
+ \edef\pgf@temp{#1}%
+ \ifx\pgf@temp\pgf@min@text%
+ \pgf@dv@lib@set@mm%
+ \let\pgf@dv@value\pgfdvmin%
+ \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@min@text}{}%
+ \else%
+ \ifx\pgf@temp\pgf@max@text%
+ \pgf@dv@lib@set@mm%
+ \let\pgf@dv@value\pgfdvmax%
+ \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@max@text}{}%
+ \else%
+ \pgfdvmathenter{\pgf@dv@value}{\pgf@temp}%
+ \fi%
+ \fi%
+ \pgfdvmathexitbyserializing{\pgf@dv@serial}{\pgf@dv@value}%
+ \pgfkeyslet{/data point/\pgfoovalueof{in}}\pgf@dv@serial%
+ }%
+ \def\pgf@dv@lib@set@mm{
+ \pgfooget{in range obj}\pgfdvinrangeinterval
+ \pgfdvinrangeinterval.get min and max()%
+ }%
+
+
+ % Slot
+ \method phase(#1) {
+ \ifx#1\pgfdvendsurvey
+ % Ok, we setup the interval mapper.
+ %
+ % We start by computing the interval borders:
+ \pgfoovalueof{in range obj}.get min and max()
+ \ifx\pgfdvmin\pgfutil@empty% undefined, since no data points
+ \else%
+ \pgfooget{scaling spec}\pgf@temp%
+ \expandafter\pgf@lib@dv@parse@scaling\pgf@temp\pgf@stop%
+ \pgfoovalueof{interval mapper}.set interval values(%
+ \pgf@lib@dv@min,\pgf@lib@dv@max,%
+ \pgf@lib@dv@min@at,\pgf@lib@dv@max@at)
+ \fi
+ \fi
+ }%
+
+
+ % Internal helper
+ \def\pgf@lib@dv@parse@scaling#1 at#2and #3 at#4\pgf@stop{%
+ \def\pgf@lib@dv@min{#1}%
+ \pgfdvmathenter{\pgf@lib@dv@min@at@mv}{#2}
+ \def\pgf@lib@dv@max{#3}%
+ \pgfdvmathenter{\pgf@lib@dv@max@at@mv}{#4}
+ \ifx\pgf@lib@dv@min\pgf@min@text%
+ \let\pgf@lib@dv@min@mv\pgfdvmin
+ \pgfoolet{spec maps min}\pgfutil@firstoftwo%
+ \else
+ \pgfdvmathenter{\pgf@lib@dv@min@mv}{\pgf@lib@dv@min}
+ \pgfoolet{spec maps min}\pgfutil@secondoftwo%
+ \fi
+ \ifx\pgf@lib@dv@max\pgf@max@text%
+ \let\pgf@lib@dv@max@mv\pgfdvmax
+ \pgfoolet{spec maps max}\pgfutil@firstoftwo%
+ \else
+ \pgfdvmathenter{\pgf@lib@dv@max@mv}{\pgf@lib@dv@max}
+ \pgfoolet{spec maps max}\pgfutil@secondoftwo%
+ \fi
+ \pgfdvmathexitbyserializing{\pgf@lib@dv@min}{\pgf@lib@dv@min@mv}
+ \pgfdvmathexitbyserializing{\pgf@lib@dv@min@at}{\pgf@lib@dv@min@at@mv}
+ \pgfdvmathexitbyserializing{\pgf@lib@dv@max}{\pgf@lib@dv@max@mv}
+ \pgfdvmathexitbyserializing{\pgf@lib@dv@max@at}{\pgf@lib@dv@max@at@mv}
+ }%
+ \def\pgf@min@text{min}%
+ \def\pgf@max@text{max}%
+}%
+
+
+
+
+
+%
+% Surveyors
+%
+
+\pgfooclass{range surveyor}
+{%
+ % Class range surveyor
+ %
+ % A range surveyor is used only in the survey phase. Its job is to
+ % determine the minimum and maximum values of an attribute that are
+ % "seen" during the survey phase. Based on this value, the size of,
+ % say, an axis can be determined later on.
+ %
+ % You can also set the key "sub attributes" of the attribute. In
+ % this case, this key should contain -- as the name suggests -- a
+ % list of subkeys that should also be taken into account for the
+ % computation of the minimum and maximum value. Inside the "sub
+ % attributes" key, each subkey should be surrounded by a call of
+ % \pgfdvsub. For instance, if there are two sub attributes "/data
+ % point/velocity/min" and "/data point/velocity/max" for a key
+ % "/data point/velocity", then "/data point/velocity/sub attributes"
+ % should be set to "\pgfdvsub{/min}\pgfdvsub{/max}".
+
+ \attribute attribute;%
+ % The to-be-surveyed attribute
+
+ \attribute interval obj;%
+ % The interval object that protocols the minimum and maximum
+ % values.
+
+
+ % Constructor
+ %
+ % #1 = the attribute
+ % #2 = handle to the interval object
+ %
+ \method range surveyor(#1,#2) {
+ \pgfooset{attribute}{#1}
+ \pgfoolet{interval obj}#2
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,survey,survey datapoint signal)
+ }%
+
+ % Method
+ %
+ % #1 = a value
+ %
+ % Adjust the interval as if during the survey this value were
+ % encountered
+ \method include attribute value(#1) {
+ \pgf@dv@assign@val@stripped#1\pgf@stop%
+ \pgfoovalueof{interval obj}.adjust(\pgf@dv@range@surv)
+ }%
+ \def\pgf@dv@assign@val@stripped#1\pgf@stop{%
+ \def\pgf@dv@val{#1}
+ }%
+
+ % Slot
+ %
+ % This slot should be connected to the survey datapoint signal. For
+ % each datapoint, this method will call the adjust method of the
+ % interval.
+ %
+ \method survey() {
+ \let\pgfdvsub\pgf@dv@range@surv@sub
+ \pgfdvsub{}%
+ \pgfkeysvalueof{/data point/\pgfoovalueof{attribute}/sub attributes}
+ }%
+
+ \def\pgf@dv@range@surv@sub#1{
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}#1}\pgf@dv@val%
+ \ifx\pgf@dv@val\relax%
+ \else%
+ \edef\pgf@dv@val{\pgf@dv@val}%
+ \ifx\pgf@dv@val\pgfutil@empty%
+ \else%
+ \pgfoovalueof{interval obj}.adjust(\pgf@dv@range@surv)%
+ \fi%
+ \fi%
+ }%
+
+ \def\pgf@dv@range@surv{%
+ \pgfdvmathenter{\pgf@dv@value}{\pgf@dv@val}%
+ % Now, protocol value
+ \ifx\pgfdvmin\pgfutil@empty%
+ \let\pgfdvmin\pgf@dv@value%
+ \else%
+ \pgfdvmathifless{\pgf@dv@value}{\pgfdvmin}{\let\pgfdvmin\pgf@dv@value}{}%
+ \fi%
+ \ifx\pgfdvmax\pgfutil@empty%
+ \let\pgfdvmax\pgf@dv@value%
+ \else%
+ \pgfdvmathifless{\pgfdvmax}{\pgf@dv@value}{\let\pgfdvmax\pgf@dv@value}{}%
+ \fi%
+ }%
+}%
+
+
+
+%
+% Visualizers
+%
+
+\usepgflibrary{plothandlers}%
+
+
+
+\pgfooclass{plot handler visualizer}
+{%
+ % Class plot handler visualizer
+ %
+ % This visualizer uses one or more plot handlers to visualize data points.
+ % As the data points are processed, the canvas positions of the data
+ % points are recorded. At the end of a group of data points, the
+ % recorded stream of canvas position is visualized (rendered)
+ % using plot handlers. For instance, when the lineto plot handler
+ % is used, the data points are connected by straight lines, when the
+ % curveto plot handler is used, they are connected by smooth curves
+ % and so on.
+ %
+ % Since plot lines are not drawn immediately, but only at the end,
+ % when everything has been collected, multiple plot handlers can
+ % coexist peacefully at the same time.
+ %
+ % You can specify a "filter", which will cause only those data
+ % points to be visualized by the visualizer that pass the test. The
+ % filter should set \pgfdvfilterpassedfalse for to-be-filtered data
+ % point.
+ %
+ % You can specify "projection code" that changes the canvas x and
+ % canvas y positions. This projection code allows you to draw, say,
+ % projected points instead of the actual data point.
+ %
+ % The keys /data point/<name>/execute at begin and /data
+ % point/<name>/execute at end, where <name> is the name of
+ % the visualizer, should store code that is to be executed directly
+ % before and after the stream of coordinates is created. Typically,
+ % these keys will store commands to use the path created by the plot
+ % handler.
+
+ \attribute handlers;%
+ % The to-be-used handlers
+
+ \attribute name;%
+ % The attribute
+
+ \attribute filter=\pgfdvnamedvisualizerfilter;%
+ % Filter code
+
+ \attribute positions;%
+ % An internal protocol of the positions on the stream
+
+ \attribute cache;%
+ % An internal cache. Positions are first inserted into this
+ % cache. Every 100 steps this cache is moved to positions. The idea
+ % behind this is that it will avoid the quadratic time increase that
+ % is normally caused when a protocol is build in TeX.
+
+ \attribute projection code;%
+ % This code is empty by default. However, you can set it for
+ % instance to the following
+ %
+ % \pgfkeyssetvalue{/data point/y=0}\pgfdvmapdatapointtocanvas
+ %
+ % in order to visualize the data point with its y-coordinate
+ % replaced by 0.
+
+ % Constructor
+ %
+ % #1 = A name
+ % #2 = A comma-separated list of handlers like
+ % "\pgfplothandlerlineto,\pgfplothandlercurveto"
+ %
+ \method plot handler visualizer(#1,#2) {
+ \pgfooset{name}{#1}
+ \pgfooset{handlers}{#2}
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,protocol,visualize datapoint signal)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Setter
+ \method set filter(#1) {
+ \pgfooset{filter}{#1}
+ }%
+
+ % Setter
+ \method set projection code(#1) {
+ \pgfooset{projection code}{#1}
+ }%
+
+ % Slot
+ \method protocol() {
+ \pgfdvfilterpassedtrue
+ \pgfoovalueof{filter}
+ \ifpgfdvfilterpassed%
+ \pgf@dv@line@cache@it
+ \fi%
+ }%
+
+ \def\pgf@dv@line@cache@it{
+ % Cache it
+ \pgfooget{cache}\pgf@dv@cache
+ \pgfkeysgetvalue{/data point/outlier}\pgf@temp%
+ \ifx\pgf@temp\pgfutil@empty
+ {%
+ \pgfoovalueof{projection code}
+ \xdef\pgf@dv@add{\noexpand\pgf@dv@ph{\pgfkeysvalueof{/data
+ point/canvas x}}{\pgfkeysvalueof{/data point/canvas y}}}%
+ }
+ \else%
+ % An outlier!
+ \gdef\pgf@dv@add{\pgf@dv@outliner}%
+ \fi%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgf@dv@cache%
+ \expandafter\expandafter\expandafter{\expandafter\pgf@dv@cache\pgf@dv@add}%
+ % Possibly flush cache
+ \global\advance\pgf@lib@dv@cache@count by1\relax%
+ \ifnum\pgf@lib@dv@cache@count=100\relax%
+ \global\pgf@lib@dv@cache@count=0\relax%
+ % Append cache to positions
+ \pgfooget{positions}\pgf@dv@temp
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgf@dv@temp%
+ \expandafter\expandafter\expandafter{\expandafter\pgf@dv@temp\pgf@dv@cache}%
+ \pgfoolet{positions}\pgf@dv@temp
+ \let\pgf@dv@cache\pgfutil@empty
+ \fi
+ \pgfoolet{cache}\pgf@dv@cache
+ }%
+
+ % Slot
+ \method phase(#1) {%
+ \ifx#1\pgfdvendvisualization%
+ \pgfoothis.render()%
+ \fi%
+ }%
+
+ % Internal method
+ \method render() {
+ \pgfscope
+ \pgfooget{handlers}\tikz@dv@temp@list
+ \foreach\tikz@dv@temp in\tikz@dv@temp@list{
+ \ifx\tikz@dv@temp\pgfutil@empty
+ \else
+ \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at begin}
+ \tikz@dv@temp
+ \pgfdvnewstreamtrue
+ \pgfoovalueof{positions}
+ \pgfoovalueof{cache}
+ \ifpgfdvnewstream\else\pgfplotstreamend\fi
+ \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at end}
+ \fi
+ }
+ \endpgfscope
+ \pgfoolet{positions}\pgfutil@empty
+ \pgfoolet{cache}\pgfutil@empty
+ }%
+
+ \def\pgf@dv@ph#1#2{\ifpgfdvnewstream\pgfplotstreamstart\pgfdvnewstreamfalse\fi\pgfplotstreampoint{\pgfqpoint{#1}{#2}}}%
+ \def\pgf@dv@outliner{\ifpgfdvnewstream\else\pgfplotstreamend\pgfdvnewstreamtrue\fi}%
+}%
+
+\newif\ifpgfdvnewstream
+\newcount\pgf@lib@dv@cache@count
+
+\pgfkeys{%
+ /data point/outlier/.initial=,
+ /data point/outlier/.default=true,
+}%
+
+
+% A possible filter for unnamed visualizers
+%
+% #1 = Text to be compared with key /data point/set
+%
+% Description:
+%
+% In a data visualization with multiple visualizers, data points
+% typically "belong" only to a single visualizer. It is, thus,
+% necessary to filter data points according to the current
+% visualizer. This current visualizer is assumed to be stored in /data
+% point/visualizer.
+%
+% When objects allow you to set a filter, you can use this filter to
+% test against /data point/set being equal to #1.
+
+\def\pgfdvvisualizerfilter#1{%
+ \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
+ \def\pgf@temp{#1}%
+ \ifx\pgf@temp\pgf@dv@visualizer%
+ \else
+ \pgfdvfilterpassedfalse
+ \fi%
+}%
+
+
+
+% A filter for named visualizer
+%
+% Description:
+%
+% This filter works like \pgfdvvisualizerfilter, only it assumes the
+% the object defines a "name" attribute. In this case, the value of
+% /data point/set is tested against this attribute.
+
+\def\pgfdvnamedvisualizerfilter{%
+ \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
+ \pgfooget{name}\pgf@temp%
+ \ifx\pgf@temp\pgf@dv@visualizer%
+ \else
+ \pgfdvfilterpassedfalse
+ \fi%
+}%
+
+
+
+\pgfooclass{rectangle visualizer}
+{%
+ % Class rectangle visualizer
+ %
+ % This visualizer visualizes a datapoint as a rectangle. It needs
+ % a name, so that /data point/<name>/attribute 1 and /data
+ % point/<name>/attribute 2 store two attributes names a1 to a2. Then,
+ % provided the current value of /data point/set equals name, for
+ % each data point a rectangle between (a1/min,a2/min) and
+ % (a1/max,a2/max) is created.
+
+
+ \attribute name;%
+ % The name
+
+ \attribute a1;%
+ \attribute a2;%
+ % The attributes, filled from /data point/<name>/attribute 1 and 2
+
+
+ % Constructor
+ %
+ % #1 = first attribute
+ % #2 = second attribute
+ %
+ \method rectangle visualizer(#1) {
+ \pgfooset{name}{#1}
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,visualize,visualize datapoint signal)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Slot
+ \method phase(#1) {%
+ \ifx#1\pgfdvbeginsurvey%
+ \pgfooeset{a1}{/data point/\pgfkeysvalueof{/data point/\pgfoovalueof{name}/attribute 1}}
+ \pgfooeset{a2}{/data point/\pgfkeysvalueof{/data point/\pgfoovalueof{name}/attribute 2}}
+ \pgfkeyssetvalue{\pgfoovalueof{a1}/sub attributes}{\pgfdvsub{/min}\pgfdvsub{/max}}
+ \pgfkeyssetvalue{\pgfoovalueof{a2}/sub attributes}{\pgfdvsub{/min}\pgfdvsub{/max}}
+ \fi%
+ }%
+
+ % Slot
+ \method visualize() {
+ {
+ \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
+ \pgfooget{name}\pgf@temp%
+ \ifx\pgf@temp\pgf@dv@visualizer%
+ \pgf@dv@rect@do
+ \fi
+ }
+ }%
+
+ \def\pgf@dv@rect@do{
+ \pgfkeysgetvalue{\pgfoovalueof{a1}/min}\pgf@dv@amin
+ \ifx\pgf@dv@amin\relax\else\ifx\pgf@dv@amin\pgfutil@empty\else
+ \pgfkeysgetvalue{\pgfoovalueof{a1}/max}\pgf@dv@amax
+ \ifx\pgf@dv@amax\relax\else\ifx\pgf@dv@amax\pgfutil@empty\else
+ \pgfkeysgetvalue{\pgfoovalueof{a2}/min}\pgf@dv@bmin
+ \ifx\pgf@dv@bmin\relax\else\ifx\pgf@dv@bmin\pgfutil@empty\else
+ \pgfkeysgetvalue{\pgfoovalueof{a2}/max}\pgf@dv@bmax
+ \ifx\pgf@dv@bmax\relax\else\ifx\pgf@dv@bmax\pgfutil@empty\else
+ \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at begin}
+ \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amin}
+ \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmin}
+ \pgfpathdvmoveto
+ \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmax}
+ \pgfpathdvlineto
+ \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amax}
+ \pgfpathdvlineto
+ \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmin}
+ \pgfpathdvlineto
+ \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amin}
+ \pgfpathdvlineto
+ \pgfpathclose
+ \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at end}
+ \fi\fi
+ \fi\fi
+ \fi\fi
+ \fi\fi
+ }%
+}%
+
+\newcount\pgf@lib@dv@cache@count
+
+
+
+%
+% Label positioning classes
+%
+
+\pgfooclass{label visualizer}
+{%
+ % Class label visualizer
+ %
+ % The job of this class is to visualize a label of a curve or some
+ % other object.
+ %
+ % The idea is as follows: This class monitors a certain
+ % attribute. When this attribute reaches a certain value for the
+ % first time, the following happens: A normalized vector of the line
+ % connecting the current canvas position to the canvas position of
+ % the previous data point is computed and stored in pgf@x/pgf@y. The
+ % coordinate system is shifted so that the current data point is at
+ % the origin. Then, some drawing code is executed.
+
+ \attribute attribute;%
+ % The monitored attribute
+
+ \attribute filter;%
+ % Filter code, see plot handler visualizer doc.
+
+ \attribute threshold;%
+ % When the attribute exceeds this threshold, the drawing code is
+ % executed
+
+ \attribute before canvas position=;%
+ % Stores canvas position of the data point before the interesting one
+
+ \attribute canvas position=;%
+ % Stores canvas position of the data point
+
+ \attribute code;%
+ % To-be-executed code when the label should be drawn
+
+
+ % Constructor
+ %
+ % #1 = attribute
+ % #2 = a macro, storing the threshold
+ % #3 = code
+ % #4 = filter code
+ %
+ \method label visualizer(#1,#2,#3,#4) {
+ \pgfooset{attribute}{#1}
+ \expandafter\pgfdvmathenter\expandafter{\expandafter\pgf@temp\expandafter}\expandafter{#2}
+ \pgfoolet{threshold}\pgf@temp
+ \pgfooset{code}{#3}
+ \pgfooset{filter}{#4}
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,test,visualize datapoint signal)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Slot
+ \method test() {
+ \pgfdvfilterpassedtrue
+ \pgfoovalueof{filter}
+ \ifpgfdvfilterpassed%
+ \pgfooget{attribute}\pgf@dv@attribute
+ \ifx\pgf@dv@attribute\pgfutil@empty%
+ % nothing to do (anymore)
+ \else%
+ \pgf@dv@label@vis@record
+ \fi%
+ \fi%
+ }%
+
+ \def\pgf@dv@label@vis@record{
+ % Record current position
+ \edef\pgf@dv@pos{%
+ \noexpand\pgfqpoint%
+ {\pgfkeysvalueof{/data point/canvas x}}%
+ {\pgfkeysvalueof{/data point/canvas y}}}%
+ \pgfooget{canvas position}\pgf@dv@temp%
+ \pgfoolet{before canvas position}\pgf@dv@temp%
+ \pgfoolet{canvas position}\pgf@dv@pos%
+ % Now check threshold
+ \pgfooget{threshold}\pgf@dv@thres%
+ \ifx\pgf@dv@thres\pgfutil@empty%
+ \else%
+ % Hmm, have to check, whether the value is, indeed, correct
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}\pgf@dv@val
+ \ifx\pgf@dv@val\relax%
+ \else\ifx\pgf@dv@val\pgfutil@empty%
+ \else%
+ \pgfdvmathenter{\pgf@dv@value}{\pgf@dv@val}%
+ \pgfooget{threshold}{\pgf@dv@thres}
+ % Now, protocol value
+ \pgfdvmathifless{\pgf@dv@value}{\pgf@dv@thres}{}{%
+ \pgfoolet{attribute}\pgfutil@empty% Stop!
+ }%
+ \fi\fi%
+ \fi%
+ }%
+
+ % Slot
+ \method phase(#1) {%
+ \ifx#1\pgfdvendvisualization%
+ \scope
+ \pgfcoordinate{label visualizer coordinate}{\pgfoovalueof{canvas position}}
+ \pgfcoordinate{label visualizer coordinate'}{\pgfoovalueof{before canvas position}}
+ \pgfoovalueof{code}
+ \endscope
+ \fi%
+ }%
+}%
+
+
+
+%
+% Style sheets
+%
+\pgfooclass{style attribute}
+{%
+ % Class style attribute
+ %
+ % Instances of this class are used to select a style based on the
+ % current value of an attribute.
+ %
+ % Instances of this class monitor an attribute. Whenever the "style"
+ % signal is raised, the object investigates the current value of the
+ % attribute. It then looks up /pgf/data visualization/style
+ % sheets/<name of style sheet>/<value of the attribute> and executes
+ % this key, provided it is defined. If it not defined, the key
+ % /pgf/data visualization/style sheets/<name of style sheet>/default
+ % style is executed with the value as a parameter.
+
+ \attribute attribute;%
+ % The name of the attribute
+
+ \attribute style sheet name;%
+ % The styling function
+
+ % Constructor
+ %
+ % #1 = attribute (including, if present, /data point/)
+ % #2 = style sheet name
+ %
+ \method style attribute(#1,#2) {
+ \pgfooset{attribute}{#1}
+ \pgfooset{style sheet name}{#2}
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,invoke style,style signal)
+ }%
+
+ % Slots
+ \method invoke style() {
+ \pgfooget{attribute}\pgf@dv@temp
+ \pgfkeysgetvalue{\pgf@dv@temp}\pgf@dv@temp@val
+ \ifx\pgf@dv@temp@val\pgfutil@empty%do nothing
+ \else\ifx\pgf@dv@temp@val\relax%do nothing
+ \else%
+ \pgfkeysifdefined{\pgf@dv@temp/\pgf@dv@temp@val}{\pgfkeysgetvalue{\pgf@dv@temp/\pgf@dv@temp@val}\pgf@dv@temp@val}{}% redirect
+ \edef\pgf@temp{/pgf/data visualization/style sheets/\pgfoovalueof{style sheet name}}
+ \pgfkeysifassignable{\pgf@temp/\pgf@dv@temp@val}{%
+ \pgfkeysalso{\pgf@temp/\pgf@dv@temp@val}}{%
+ \pgfkeysalso{\pgf@temp/default style/.expand once=\pgf@dv@temp@val}
+ }
+ \fi\fi%
+ }%
+}%
+
+
+% Declares a new style sheet
+%
+% #1 = name of style sheet
+% #2 = settings
+%
+% Description:
+%
+% This is a shortcut for doing a /.cd to /pgf/data visualization/style sheets/#1
+
+\def\pgfdvdeclarestylesheet#1#2{
+ \pgfkeys{/pgf/data visualization/style sheets/#1/.cd,#2}
+}%
+
+
+
+
+
+
+
+
+
+%
+% Legend container class
+%
+
+\pgfooclass{legend}
+{%
+ % Class legend
+ %
+ % This class is used to collect entries into a legend. The idea is
+ % that, say, for each line of a picture you would like to have an
+ % entry in a legend. Then you prepare these entries and send
+ % them to a legend container object. It will collect the entries
+ % and, at the end, arrange them in rows and columns by
+ % separating them using \pgfdvnextcell and \pgfdvendrow.
+ %
+ % By surrounding the resulting arrangement by a call to \pgfmatrix or
+ % a call to \halign you can then create a legend.
+ %
+ % To specify how the entries should be arranged, a size
+ % specification and two directions are needed.
+ %
+ % For the size specification you specify either the ideal number of
+ % columns and the maximum number of rows or you specify the ideal
+ % number of rows and the maximum number of columns. In the first
+ % case, the class first tries to create as many columns as specified
+ % by the "ideal" parameter. If there are less entries than this
+ % parameter, you obviously get less columns, namely as many as there
+ % are entries, each column containing only one entry. If there are
+ % more entries that the ideal number of columns, you get multiple
+ % columns, each containing as many entries to make sure that the
+ % ideal number is met. However, if a column would get more than the
+ % specified maximum number of elements per column, you get more
+ % columns that the ideal number -- to ensure that no column contains
+ % more than the desired number. The case is symmetric, but with the
+ % roles of columns and rows exchanged.
+ %
+ % Here is an example: You specify that you want 2 columns, ideally,
+ % each having a maximum of 4 entries. Here is what you would get:
+ %
+ % Number of entries & Number of resulting columns ... & ... and rows
+ % 1 & 1 & 1
+ % 2 & 2 & 1
+ % 3 & 2 & 2
+ % 4 & 2 & 2
+ % 5 & 2 & 3
+ % 6 & 2 & 3
+ % 7 & 2 & 4
+ % 8 & 2 & 4
+ % 9 & 3 & 4
+ % 10 & 3 & 4
+ % 11 & 3 & 4
+ % 12 & 3 & 4
+ % 13 & 4 & 4
+ %
+ %
+ % Once the number of columns and rows has been computed, the next
+ % step is to "fill" the table. For this, eight strategies may be
+ % specified: right then down, right then up, left then down, left
+ % then up, up then right, up then left, down then right, down then
+ % left. A strategy like "right then up" means the following: Each
+ % new entry should placed right of the previous entry in the
+ % arrangement. However, once the maximum number of elements in a row
+ % has been reached, the a new row should be started that is placed
+ % above ("up") then just-assembled row.
+ %
+ %
+ %
+ %
+ % Example:
+ %
+ % You create an object \legend and then call
+ %
+ % \pgfoofnew \legend=new legend(columns,2,3,down then right)
+ % \legend.add entry(first)
+ % \legend.add entry(second)
+ % \legend.add entry(third)
+ % \legend.add entry(fourth)
+ % \legend.add entry(fifth)
+ % \legend.add entry(sixth)
+ % \legend.add entry(seventh)
+ % \legend.get arrangement(\arrangement)
+ %
+ % Then \arrangment will expand to
+ %
+ % first \pgfdvnextcell fourth \pgfdvnextcell seventh \pgfdvendrow
+ % second \pgfdvnextcell fifth \pgfdvnextcell third \pgfdvendrow
+ % third \pgfdvendrow sixth \pgfdvnextcell \pgfdvendrow
+ %
+ % By saying \let\pgfdvendrow=\\ and \let\pgfdvnextcell=&, you
+ % can use \arrangment inside a table.
+
+
+ \attribute entries;%
+ % Collects the entries
+
+ \attribute columns or rows;%
+ % Specifies whether columns or rows are specified
+
+ \attribute ideal;%
+ % The ideal number of columns/rows
+
+ \attribute max;%
+ % The maximum number of entries per column/row
+
+ \attribute strategy;%
+ % Specifies how the matrix should be filled
+
+ \attribute number of entries=0;%
+ % Counts the number of entries that have been stored
+
+
+ % Constructor
+ %
+ % #1 = "columns" or "rows" -> specifies whether the ideal number and
+ % the max entries number refer to columns or the row
+ % #2 = the ideal number of #1's
+ % #3 = the maximum number of entries in a #1
+ % #4 = one of the eight strategies
+ %
+ \method legend(#1,#2,#3,#4) {
+ \pgfooset{columns or rows}{#1}
+ \pgfooset{ideal}{#2}
+ \pgfooset{max}{#3}
+ \pgfooset{strategy}{#4}
+ }%
+
+ % Method
+ \method default connects() {
+ }%
+
+ % Method
+ \method add entry(#1) {
+ \pgfooappend{entries}{{#1}}
+ \c@pgf@counta=\pgfoovalueof{number of entries}\relax%
+ \advance\c@pgf@counta by1\relax%
+ \pgfooeset{number of entries}{\the\c@pgf@counta}
+ }%
+
+ % Method
+ \method get arrangement(#1) {
+ {
+ %
+ % Step 1: Compute the desired number of rows or columns
+ %
+ %
+ % Compute the ideal number of entries per row/column (called
+ % "target" in the following) and entries per colum/row (called
+ % "per target" in the following)
+ %
+ % if (number of entries > ideal)
+ \ifnum\pgfoovalueof{number of entries}>\pgfoovalueof{ideal}\relax%
+ % {
+ % if (ideal * max > number of entries)
+ \c@pgf@counta=\pgfoovalueof{ideal}\relax%
+ \multiply\c@pgf@counta by\pgfoovalueof{max}\relax%
+ \ifnum\c@pgf@counta>\pgfoovalueof{number of entries}\relax
+ % {
+ % target = ideal;
+ % per target = ceil (number of entries / ideal);
+ \c@pgf@counta=\pgfoovalueof{ideal}\relax%
+ \c@pgf@countb=\pgfoovalueof{number of entries}\relax
+ \advance\c@pgf@countb by-1\relax
+ \divide\c@pgf@countb by\c@pgf@counta\relax%
+ \advance\c@pgf@countb by1\relax%
+ % }
+ % else
+ % {
+ % target = ceil(number of entries / max);
+ % per target = max;
+ \else
+ \c@pgf@countb=\pgfoovalueof{max}\relax%
+ \c@pgf@counta=\pgfoovalueof{number of entries}\relax
+ \advance\c@pgf@counta by-1\relax
+ \divide\c@pgf@counta by\c@pgf@countb\relax%
+ \advance\c@pgf@counta by1\relax%
+ \fi
+ % }
+ % }
+ % else
+ % {
+ % target = number of entries;
+ % per target = 1;
+ % }
+ \else
+ \c@pgf@counta=\pgfoovalueof{number of entries}\relax%
+ \c@pgf@countb=1\relax%
+ \fi%
+ %
+ % Ensure that counta = rows, countb = columns
+ %
+ \pgfooget{columns or rows}\pgf@temp
+ \ifx\pgf@temp\pgf@dv@columnstext%
+ \c@pgf@countc=\c@pgf@counta\relax
+ \c@pgf@counta=\c@pgf@countb\relax
+ \c@pgf@countb=\c@pgf@countc\relax
+ \fi
+ %\edef\temp{rows: \the\c@pgf@counta, columns: \the\c@pgf@countb}\temp
+ %
+ % Now arrange the matrix
+ %
+ \csname pgf@dv@legend@init@\pgfoovalueof{strategy}\endcsname
+ \expandafter\let\expandafter\pgf@dv@updater\csname pgf@dv@legend@update@\pgfoovalueof{strategy}\endcsname
+ \pgfooget{entries}\pgf@temp
+ \expandafter\pgf@dv@legend@arrange\pgf@temp\pgf@stop
+ %
+ % Now assemble the matrix
+ %
+ \edef\pgf@dv@row@list{1,...,\the\c@pgf@counta}
+ \edef\pgf@dv@column@list{1,...,\the\c@pgf@countb}
+ \global\let\pgf@dv@matrix\pgfutil@empty
+ \foreach \pgf@dv@row in \pgf@dv@row@list
+ {
+ \global\let\pgf@dv@matrix@row\pgf@dv@first@mark
+ \foreach \pgf@dv@column in \pgf@dv@column@list
+ {
+ \expandafter\let\expandafter\pgf@temp\csname pgf@dv@legend@entry@\pgf@dv@row @\pgf@dv@column\endcsname
+ \ifx\pgf@temp\relax
+ \let\pgf@temp\pgfutil@empty
+ \fi
+ \ifx\pgf@dv@matrix@row\pgf@dv@first@mark
+ \global\let\pgf@dv@matrix@row\pgf@temp
+ \else
+ \expandafter\pgfutil@g@addto@macro\expandafter\pgf@dv@matrix@row\expandafter{\expandafter\pgfdvnextcell\pgf@temp}
+ \fi
+ }
+ \pgfutil@g@addto@macro\pgf@dv@matrix@row{\pgfdvendrow}
+ \expandafter\pgfutil@g@addto@macro\expandafter\pgf@dv@matrix\expandafter{\pgf@dv@matrix@row}
+ }
+ \global\let\pgf@dv@matrix@row\relax
+ }
+ \let#1\pgf@dv@matrix
+ \global\let\pgf@dv@matrix\relax
+ }%
+
+ \def\pgf@dv@first@mark{\pgf@dv@first@mark}%
+
+ \def\pgf@dv@legend@arrange{%
+ \pgfutil@ifnextchar\pgf@stop{\pgfutil@gobble}{\pgf@dv@legend@handle@entry}
+ }%
+
+ \def\pgf@dv@legend@handle@entry#1{
+ \expandafter\def\csname pgf@dv@legend@entry@\the\c@pgf@countc @\the\c@pgf@countd\endcsname{#1}%
+ \pgf@dv@updater%
+ \pgf@dv@legend@arrange%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@down then right\endcsname{%
+ \c@pgf@countc=1\relax%
+ \c@pgf@countd=1\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@down then right\endcsname{%
+ \advance\c@pgf@countc by1\relax
+ \ifnum\c@pgf@countc>\c@pgf@counta\relax%
+ \c@pgf@countc=1\relax%
+ \advance\c@pgf@countd by1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@right then down\endcsname{%
+ \c@pgf@countc=1\relax%
+ \c@pgf@countd=1\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@right then down\endcsname{%
+ \advance\c@pgf@countd by1\relax
+ \ifnum\c@pgf@countd>\c@pgf@countb\relax%
+ \c@pgf@countd=1\relax%
+ \advance\c@pgf@countc by1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@up then right\endcsname{%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \c@pgf@countd=1\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@up then right\endcsname{%
+ \advance\c@pgf@countc by-1\relax
+ \ifnum\c@pgf@countc=0\relax%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \advance\c@pgf@countd by1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@right then up\endcsname{%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \c@pgf@countd=1\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@right then up\endcsname{%
+ \advance\c@pgf@countd by1\relax
+ \ifnum\c@pgf@countd>\c@pgf@countb\relax%
+ \c@pgf@countd=1\relax%
+ \advance\c@pgf@countc by-1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@left then up\endcsname{%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@left then up\endcsname{%
+ \advance\c@pgf@countd by-1\relax
+ \ifnum\c@pgf@countd=0\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ \advance\c@pgf@countc by-1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@up then left\endcsname{%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@up then left\endcsname{%
+ \advance\c@pgf@countc by-1\relax
+ \ifnum\c@pgf@countc=0\relax%
+ \c@pgf@countc=\c@pgf@counta\relax%
+ \advance\c@pgf@countd by-1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@left then down\endcsname{%
+ \c@pgf@countc=1\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@left then down\endcsname{%
+ \advance\c@pgf@countd by-1\relax
+ \ifnum\c@pgf@countd=0\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ \advance\c@pgf@countc by1\relax%
+ \fi%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@init@down then left\endcsname{%
+ \c@pgf@countc=1\relax%
+ \c@pgf@countd=\c@pgf@countb\relax%
+ }%
+
+ \expandafter\def\csname pgf@dv@legend@update@down then left\endcsname{%
+ \advance\c@pgf@countc by1\relax
+ \ifnum\c@pgf@countc>\c@pgf@countb\relax%
+ \c@pgf@countc=1\relax%
+ \advance\c@pgf@countd by-1\relax%
+ \fi%
+ }%
+
+ \def\pgf@dv@columnstext{columns}%
+}%
+
+
+
+%
+% Help classes
+%
+
+\pgfooclass{interval}
+{%
+ % Class interval
+ %
+ % Instances of this class store intervals. When either the min or
+ % the max value is empty, this corresponds to "not yet set", (not to
+ % "infinity).
+
+ \attribute min;%
+ % The minimum value of the interval
+
+ \attribute max;%
+ % The maximum value of the interval
+
+ % Constructor
+ %
+ % #1 = initial minimum value
+ % #2 = initial maximum value
+ %
+ \method interval(#1,#2) {
+ \pgfooset{min}{#1}
+ \pgfooset{max}{#2}
+ }%
+
+ % Method
+ \method default connects() {
+ }%
+
+ % Sets the minimum/maximum to a new value
+ \method set min(#1) {
+ \pgfooset{min}{#1}
+ }%
+ \method set max(#1) {
+ \pgfooset{max}{#1}
+ }%
+ \method let min(#1) {
+ \pgfoolet{min}{#1}
+ }%
+ \method let max(#1) {
+ \pgfoolet{max}{#1}
+ }%
+
+ % Getter
+ %
+ % Returns the current values of the minimum and maximum in the
+ % macros \pgfdvmin and \pgfdvmax.
+ \method get min and max() {
+ \pgfooget{min}\pgfdvmin
+ \pgfooget{max}\pgfdvmax
+ }%
+
+ % Adjusts the minimum and maximum values
+ %
+ % #1 = some code. When this code is executed, the values of
+ % \pgfdvmin and \pgfdvmax will be set to the current values of
+ % the minimum/maximum. The code may change these values. The
+ % changed values will then be stored.
+ %
+ % This method does nothing that cannot be achieved also by calling
+ % set/get methods, but it is easier to use and faster.
+ \method adjust(#1) {
+ {%
+ \pgfooget{min}\pgfdvmin
+ \pgfooget{max}\pgfdvmax
+ #1%
+ \pgfoolet{min}\pgfdvmin
+ \pgfoolet{max}\pgfdvmax
+ }%
+ }%
+}%
+
+
+
+\pgfooclass{count}
+{%
+ % Class count
+ %
+ % This class can be used to count the number of data points that are
+ % present or that have a certain property. By default, for every
+ % data point a counter is incremented and the value of this counter
+ % is stored in an attribute. You can also specify an increment for
+ % the counter. You can specify that certain data points should
+ % not have an effect on the counter.
+
+
+ \attribute attribute;%
+ % The attribute that will be set to the current value of the counter
+
+ \attribute val=0;%
+ % The current value of the counter
+
+ \attribute max=0;%
+ % The current value of the counter
+
+ \attribute step=1;%
+ % The stepping by which the counter is incremented for each
+ % datapoint
+
+ \attribute start val=0;%
+ % The start value of the counter
+
+ \attribute filter=;%
+ % This attribute stores some code that is executed for each
+ % data point. If the data point sets the TeX-if ifpgfdvfilterpassed to
+ % true, then the counter is not incremented.
+
+
+ % Constructor
+ %
+ % #1 = The attribute in which the counter value is stored
+ %
+ \method count(#1) {
+ \pgfooset{attribute}{#1}
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,apply,prepare datapoint signal)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Getter
+ \method get max(#1) {
+ \pgfooget{max}{#1}
+ }%
+
+ % Setter
+ \method set value(#1) {
+ \pgfooset{val}{#1}
+ \pgfkeyssetvalue{/data point/\pgfoovalueof{attribute}}{#1}%
+ }%
+
+ % Setter
+ \method set start value(#1) {
+ \pgfooset{start val}{#1}
+ \pgfooset{max}{#1}
+ }%
+
+ % Setter
+ \method set filter(#1) {
+ \pgfooset{filter}{#1}
+ }%
+
+ % Setter
+ \method set step(#1) {
+ \pgfooset{step}{#1}
+ }%
+
+ % Slot
+ \method apply() {
+ \pgfdvfilterpassedtrue%
+ \pgfoovalueof{filter}%
+ \ifpgfdvfilterpassed%
+ \pgfmathparse{\pgfoovalueof{val}+\pgfoovalueof{step}}%
+ \pgfoolet{val}\pgfmathresult%
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}}\pgfmathresult%
+ \ifdim\pgfmathresult pt>\pgfoovalueof{max}pt\relax%
+ \pgfoolet{max}\pgfmathresult%
+ \fi%
+ \pgfooget{max}\pgfmathresult%
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}/max}\pgfmathresult%
+ \fi%
+ }%
+
+ % Slot
+ \method phase(#1) {
+ \ifx#1\pgfdvbeginsurvey
+ \pgfooeset{val}{\pgfoovalueof{start val}}
+ \else \ifx#1\pgfdvbeginvisualization
+ \pgfooeset{val}{\pgfoovalueof{start val}}
+ \fi\fi
+ }%
+}%
+
+\newif\ifpgfdvfilterpassed
+
+
+
+
+\pgfooclass{accumulator}
+{%
+ % Class accumulator
+ %
+ % This class is used to keep track of the sum of the values of some
+ % attribute. When this object is connected to some attribute, the
+ % subkey attribute/sum will always contain the sum of all values in
+ % all previous data points with respect to this
+ % attribute. Furthermore, the subkey attribute/prev key will hold
+ % the previous sum, which is sometimes also useful to have access
+ % to.
+
+ \attribute attribute;%
+ % The attribute to-be-accumulated
+
+ \attribute sum;%
+ % The initial value of the sum
+
+ % Constructor
+ %
+ % #1 = to-be-accumulated attribute
+ \method accumulator(#1) {
+ \pgfooset{attribute}{#1}
+ \pgfoothis.reset()
+ }%
+
+ % Method
+ \method default connects() {
+ \pgfoothis.get handle(\pgf@dv@me)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,apply,prepare datapoint signal)
+ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
+ }%
+
+ % Slot
+ \method apply() {%
+ % Save old sum
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}/sum}\pgf@temp%
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}/prev sum}\pgf@temp%
+ % Add new attribute...
+ \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}{\pgf@temp@b}%
+ \pgfdvmathenter{\pgf@dv@new@val}{\pgf@temp@b}%
+ % ... to sum
+ \pgfooget{sum}\pgf@dv@sum%
+ \pgfdvmathadd{\pgf@dv@sum}{\pgf@dv@new@val}{\pgf@dv@sum}%
+ \pgfoolet{sum}\pgf@dv@sum
+ % Record in attribute
+ \pgfdvmathexitbyscientificformat{\pgf@dv@serial@sum}{\pgf@dv@sum}
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}/sum}\pgf@dv@serial@sum
+ }%
+
+ % Method
+ %
+ % Use this method to reset the sum at any point.
+ %
+ \method reset() {
+ \pgfdvmathenter{\pgf@dv@temp}{0}
+ \pgfoolet{sum}{\pgf@dv@temp}
+ \pgfdvmathexitbyserializing{\pgf@dv@zero}{\pgf@dv@temp}
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}/prev sum}{\pgf@dv@zero}
+ \pgfkeyslet{/data point/\pgfoovalueof{attribute}/sum}{\pgf@dv@zero}
+ }%
+
+ % Slot
+ \method phase(#1) {
+ \ifx#1\pgfdvbeginsurvey
+ \pgfoothis.reset()
+ \else \ifx#1\pgfdvbeginvisualization
+ \pgfoothis.reset()
+ \fi\fi
+ }%
+}%
+
+
+
+
+
+
+
+%
+%
+% Help keys and, attributes
+%
+%
+
+\pgfkeys{% do not even think of changing the values of the following:
+ /data point/always true/.initial=true,
+ /data point/always false/.initial=false,
+ /data point/always 0/.initial=0,
+ /data point/always 1/.initial=1,
+ /data point/always empty/.initial=,
+ /data point/always pgfusepath stroke/.initial=\pgfusepath{stroke},
+}%
+
+\pgfdvmathenter{\pgfdvmathalwaysloge}{0.434294481903252}%
+\pgfdvmathenter{\pgfdvmathalwayslnten}{2.302585092994046}%
+\pgfdvmathenter{\pgfdvmathalwayszero}{0}%
+\pgfdvmathenter{\pgfdvmathalwaysone}{1}%
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduledecorations.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduledecorations.code.tex
new file mode 100644
index 0000000000..c119dd622f
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduledecorations.code.tex
@@ -0,0 +1,2191 @@
+% Copyright 2019 by Mark Wibrow and 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.
+
+
+% The following naming conventions are (more or less) observed:
+%
+% `decorated' : the path that is being decorated.
+% `decoration' : any path created/left by the automaton
+% `decorate' : generic use where distinction is probably unimportant
+% (e.g. internal macros).
+
+
+
+% These should be moved.
+%
+\def\pgfgetpath#1{\pgfsyssoftpath@getcurrentpath{#1}}%
+\def\pgfsetpath#1{\pgfsyssoftpath@setcurrentpath{#1}}%
+
+
+% Required registers.
+%
+\newdimen\pgfdecoratedcompleteddistance
+\newdimen\pgfdecoratedremainingdistance
+\newdimen\pgfdecoratedinputsegmentcompleteddistance
+\newdimen\pgfdecoratedinputsegmentremainingdistance
+\newdimen\pgf@decorate@distancetomove
+
+\newcount\pgf@decorate@repeatstate
+
+
+% Extra options used in all libraries
+
+\newdimen\pgfdecorationsegmentamplitude
+\newdimen\pgfdecorationsegmentlength
+\pgfdecorationsegmentamplitude2.5pt
+\pgfdecorationsegmentlength10pt
+\def\pgfdecorationsegmentangle{45}%
+\def\pgfdecorationsegmentaspect{0.5}%
+\def\pgfmetadecorationsegmentamplitude{2.5pt}%
+\def\pgfmetadecorationsegmentlength{1cm}%
+
+\pgfkeys{%
+ /pgf/decoration/.code={\pgfkeys{/pgf/decoration/.cd,#1}},
+ /pgf/decoration/.cd,
+ amplitude/.code={\pgfmathsetlength\pgfdecorationsegmentamplitude{#1}},
+ meta-amplitude/.store in=\pgfmetadecorationsegmentamplitude,
+ segment length/.code={\pgfmathsetlength\pgfdecorationsegmentlength{#1}},
+ meta-segment length/.store in=\pgfmetadecorationsegmentlength,
+ angle/.code={\pgfmathparse{#1}\let\pgfdecorationsegmentangle\pgfmathresult},
+ aspect/.code={\pgfmathparse{#1}\let\pgfdecorationsegmentaspect\pgfmathresult},
+ start radius/.initial=2.5pt,
+ end radius/.initial=2.5pt,
+ radius/.style={start radius={#1},end radius={#1}},
+ path has corners/.is if=pgfdecoratepathhascorners,
+ reverse path/.is if=pgf@decorate@inputsegmentobjects@reverse,
+}%
+\newif\ifpgfdecoratepathhascorners
+\newif\ifpgf@decorate@inputsegmentobjects@reverse
+
+% Declare a decoration
+%
+% #1 = name of the decoration
+% #2 = initial state
+% #3 = states
+%
+% This command declares a new decoration for later use.
+% Inside the code of #3 the command \state may be used. This command
+% will only be defined while #3 is executed.
+%
+% Example:
+%
+% \pgfdeclaredecoration{zigzag}{q}
+% {
+% \state{q}[width=10pt]
+% {
+% \pgfpathlineto{\pgfpoint{2.5pt}{2.5pt}}
+% \pgfpathlineto{\pgfpoint{7.5pt}{-2.5pt}}
+% \pgfpathlineto{\pgfpoint{10pt}{0pt}}
+% }
+% \state{final}
+% {
+% \pgfpathlineto{\pgfpointdecoratedpathlast}
+% }
+% }
+
+\long\def\pgfdeclaredecoration#1#2#3{%
+ \let\pgf@mod@dec@next=\pgf@mod@dec@firstofone%
+ \pgfifmetadecoration{#1}{%
+ \pgferror{You cannot declare a decoration of the same
+ name as a meta-decoration}%
+ \let\pgf@mod@dec@next=\pgfutil@gobble%
+ }{}%
+ \pgf@mod@dec@next
+ {%
+ \def\pgf@decorate@name{#1}%
+ \pgfutil@namedef{pgf@decorate@@#1@initial}{#2}%
+ \let\pgf@orig@state\state%
+ \let\state\pgf@decorate@state
+ #3%
+ \let\state\pgf@orig@state%
+ }%
+}%
+
+\def\pgf@decorate@state#1{\pgfutil@ifnextchar[{\pgf@decorate@@start#1}{\pgf@decorate@@start#1[]}}%}%
+\def\pgf@decorate@@start#1[#2]#3{%
+ \pgfutil@namedef{pgf@decorate@@\pgf@decorate@name @#1@options}{#2}%
+ \pgfutil@namedef{pgf@decorate@@\pgf@decorate@name @#1@code}{#3}%
+}%
+\long\def\pgf@mod@dec@firstofone#1{#1}%
+
+
+% Test whether something is a decoration
+%
+% #1 = name
+% #2 = if-code
+% #3 = else-code
+%
+% Example:
+%
+% \pgfifdecoration{zigzag}{Exists}{Does not exist}
+
+\def\pgfifdecoration#1#2#3{\pgfutil@ifundefined{pgf@decorate@@#1@initial}{#3}{#2}}%
+
+
+
+% Declare a meta decoration
+%
+% #1 = name of the meta decoration
+% #2 = initial state
+% #3 = states
+%
+% This command declares a new meta decoration for later use.
+% Inside the code of #3 the command \state may be used.
+
+\long\def\pgfdeclaremetadecoration#1#2#3{%
+ \let\pgf@mod@dec@next=\pgf@mod@dec@firstofone%
+ \pgfifdecoration{#1}{%
+ \pgferror{You cannot declare a meta-decoration of the
+ same name as a decoration}%
+ \let\pgf@mod@dec@next=\pgfutil@gobble%
+ }{}%
+ \pgf@mod@dec@next{%
+ \def\pgf@metadecoration@name{#1}%
+ \pgfutil@namedef{pgf@metadecoration@@#1@initial}{#2}%
+ \let\pgf@orig@state\state%
+ \let\state\pgf@metadecoration@state
+ #3%
+ \let\state\pgf@orig@state%
+ }%
+}%
+
+\def\pgf@metadecoration@state#1{\pgfutil@ifnextchar[{\pgf@metadecoration@@state#1}{\pgf@metadecoration@@state#1[]}}%}%
+\def\pgf@metadecoration@@state#1[#2]#3{%
+ \pgfutil@namedef{pgf@metadecoration@@\pgf@metadecoration@name @#1@options}{#2}%
+ \pgfutil@namedef{pgf@metadecoration@@\pgf@metadecoration@name @#1@code}{#3}%
+}%
+
+
+% Test whether something is a meta-decoration
+%
+% #1 = name
+% #2 = if-code
+% #3 = else-code
+%
+% Example:
+%
+% \pgfifmetadecoration{zigzag}{Exists}{Does not exist}
+
+\def\pgfifmetadecoration#1#2#3{\pgfutil@ifundefined{pgf@metadecoration@@#1@initial}{#3}{#2}}%
+
+
+
+
+
+\let\pgfdecoratebeforecode\pgfutil@empty
+\let\pgfdecorateaftercode\pgfutil@empty
+
+% \pgfdecoratepath
+%
+% Decorate a path.
+%
+% \pgfdecoratebeforecode and \pgfdecorateaftercode can be used to
+% execute code before and after the decoration.
+%
+% #1 - the name of the decoration.
+% #2 - a (non-empty) path specification.
+%
+% Example:
+%
+% \pgfdeclaredecoration{circles}{red circles}{
+% \state{red circles}[width=10pt, repeat state=2, next state=blue circles]
+% {
+% \pgfmathparse{round(rnd*100)}
+% \pgfsetstrokecolor{red!\pgfmathresult!brown}
+% \pgfsetfillcolor{orange!\pgfmathresult!yellow}
+% \pgfpathcircle{\pgfpointorigin}{2.5pt}
+% \pgfusepath{stroke,fill}
+% }
+% \state{blue circles}[width=10pt, repeat state=1, next state=red circles]
+% {
+% \pgfmathparse{round(rnd*100)}
+% \pgfsetstrokecolor{blue!\pgfmathresult!gray}
+% \pgfsetfillcolor{blue!\pgfmathresult!white}
+% \pgfpathcircle{\pgfpointorigin}{2.5pt}
+% \pgfusepath{stroke,fill}
+% }
+% \state{final}{}
+% }
+%
+% \pgfpicture
+% \pgfdecoratepath{circles}
+% {
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfpoint{0cm}{3cm}}{\pgfpoint{4cm}{0cm}}{\pgfpoint{4cm}{3cm}}
+% }
+% \endpgfpicture
+%
+\long\def\pgfdecoratepath#1#2{%
+ \pgfdecoration{{#1}{\pgfdecoratedpathlength}{\pgfdecoratebeforecode}{\pgfdecorateaftercode}}%
+ #2%
+ \endpgfdecoration}%
+
+
+
+
+% \pgfdecoratecurrentpath
+%
+% Decorate the current/existing path, but (unavoidably) destroys it.
+%
+% \pgfdecoratebeforecode and \pgfdecorateaftercode can be used to
+% execute code before and after the decoration.
+%
+% #1 - the name of the decoration.
+%
+% Example:
+%
+% \pgfdeclaredecoration{stars}{move}{
+% \state{move}[width=7.5pt, next state=star]{}
+% \state{star}[width=7.5pt, next state=move]
+% {
+% \pgfmathparse{round(rnd*100)}
+% \pgfsetfillcolor{yellow!\pgfmathresult!orange}
+% \pgfsetstrokecolor{yellow!\pgfmathresult!red}
+% \pgfmathparse{rnd*.75+.25}
+% \pgftransformscale{\pgfmathresult}
+% \pgfnode{star}{center}{}{}{\pgfusepath{stroke,fill}}
+% }
+% \state{final}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathlast}
+% }
+% }
+%
+% \pgfpicture
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfqpoint{0cm}{2cm}}{\pgfqpoint{3cm}{2cm}}{\pgfqpoint{3cm}{0cm}}
+% \pgfpathcurveto{\pgfqpoint{3cm}{-3cm}}{\pgfqpoint{0cm}{0cm}}{\pgfqpoint{0cm}{-3cm}}
+% \pgfpathcurveto{\pgfqpoint{0cm}{-5cm}}{\pgfqpoint{3cm}{-5cm}}{\pgfqpoint{3cm}{-3cm}}
+% \pgfdecoratecurrentpath{stars}
+% \endpgfpicture
+%
+\def\pgfdecoratecurrentpath#1{%
+ \pgfgetpath\pgf@decorate@currentpath%
+ \pgfsetpath\pgfutil@empty%
+ \pgfdecoration{{#1}{\pgfdecoratedpathlength}{\pgfdecoratebeforecode}{\pgfdecorateaftercode}}%
+ \pgfsetpath\pgf@decorate@currentpath%
+ \endpgfdecoration}%
+
+
+
+
+% Environment \pgfdecoration \endpgfdecoration
+%
+% Decorates a path with multiple decorations.
+%
+% Definitions:
+%
+% `existing path'
+% - any unused path existing prior to the environment.
+%
+% `decorated path'
+% - the path that is being decorated.
+%
+% `decoration path'
+% - any unused path left by the decoration automaton.
+%
+% The action of the environment is as follows:
+%
+% 1. Any existing path is saved.
+% 2. Construction commands are executed forming the decorated path.
+% 3. If the first command in the decorated path is not a `move to',
+% the last known position from the existing path is inserted.
+% 4. The saved existing path is reinstalled.
+% 5. The decoration automaton is executed along the decorated path.
+%
+% Parameters:
+%
+% #1 - a comma separated list of decoration specifications.
+%
+% A decoration specification takes the format:
+%
+% {<name>}{<distance>}{<before code>}{<after code>}
+%
+% The decoration <name> is applied to a section of the decorated
+% path from the last point on the decorated path the decoration
+% automaton reached to <distance> from that point.
+%
+% When <distance>} is parsed, the dimension
+% \pgfdecoratedreminingdistance holds the distance remaining on the
+% entire decorated path, and the macro \pgfdecoratedpathlength holds
+% the total length of the entire decorated path.
+% After <distance> is parsed, both are set to to the value of
+% <distance> for the automaton to decorate current section of the
+% decorated path.
+%
+% <before code> is executed just before the decoration automaton
+% starts and <after code> is executed just after the automaton stops.
+% If <before code> or <after code> are empty, they can be omitted.
+% The macros \pgfdecoratedpathfirst and \pgfdecoratedpathlast
+% will be set up as the first and last points on the current section
+% of the decorated path.
+%
+% When the environment exits, the following macros will be set up:
+%
+% \pgfdecorateexistingpath
+% - the existing path.
+%
+% \pgfdecoratedpath
+% - the decorated path.
+%
+% \pgfdecorationpath
+% - any unused decoration path.
+%
+% \pgfpointdecoratedpathlast
+% - the last point on the decorated path.
+%
+% Examples (require pgfdecorations library):
+%
+% \pgfpicture
+% \pgfdecoration
+% {
+% {lineto}{\pgfdecoratedpathlength/3},
+% {zigzag}{\pgfdecoratedpathlength/3},
+% {lineto}{\pgfdecoratedpathlength/3}
+% }
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfpoint{0cm}{4cm}}{\pgfpoint{5cm}{0cm}}{\pgfpoint{5cm}{4cm}}
+% \endpgfdecoration
+% \pgfusepath{stroke}
+% \endpgfpicture
+%
+%
+% \pgfpicture
+% \pgfdecoration
+% {
+% {lineto}{\pgfdecoratedpathlength/5}{}{\pgfusepath{stroke}},
+% {zigzag}{\pgfdecoratedpathlength/5}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathfirst}
+% }
+% {
+% \pgfsetstrokecolor{red}
+% \pgfusepath{stroke}
+% },
+% {lineto}{\pgfdecoratedpathlength/5}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathfirst}
+% }
+% {
+% \pgfsetstrokecolor{black}
+% \pgfusepath{stroke}
+% },
+% {zigzag}{\pgfdecoratedpathlength/5}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathfirst}
+% }
+% {
+% \pgfsetstrokecolor{red}
+% \pgfusepath{stroke}
+% },
+% {lineto}{\pgfdecoratedpathlength/5}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathfirst}
+% }
+% {
+% \pgfsetstrokecolor{black}
+% \pgfusepath{stroke}
+% }
+% }
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfpoint{0cm}{4cm}}{\pgfpoint{5cm}{0cm}}{\pgfpoint{5cm}{4cm}}
+% \endpgfdecoration
+%
+% \endpgfpicture
+%
+%
+%
+% \pgfdeclaredecoration{polygons}{move}{
+% \state{move}[width=7.5pt, next state=polygon]{}
+% \state{polygon}[width=7.5pt, next state=move]
+% {
+% \pgfmathparse{round(rnd*100)}
+% \pgfsetfillcolor{green!\pgfmathresult!yellow}
+% \pgfsetstrokecolor{green!\pgfmathresult!brown}
+% \pgfnode{regular polygon}{center}{}{}{\pgfusepath{stroke,fill}}
+% }
+% \state{final}
+% {
+% \pgfpathmoveto{\pgfpointdecoratedpathlast}
+% }
+% }
+%
+% \pgfpicture
+% \pgfdecoration
+% {
+% {polygons}{45pt},
+% {lineto}{30pt}
+% {\pgfpathmoveto{\pgfpointdecoratedpathfirst}}
+% {
+% \pgfsetstrokecolor{yellow!50!orange}
+% \pgfusepath{stroke}
+% },
+% {polygons}{45pt},
+% {lineto}{30pt}
+% {\pgfpathmoveto{\pgfpointdecoratedpathfirst}}
+% {
+% \pgfsetstrokecolor{green!50!blue}
+% \pgfusepath{stroke}
+% },
+% {polygons}{\pgfdecoratedremainingdistance}
+% }
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfpoint{0cm}{4cm}}{\pgfpoint{5cm}{0cm}}{\pgfpoint{5cm}{4cm}}
+% \endpgfdecoration
+% \endpgfpicture
+%
+%
+% \pgfpicture
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfpoint{0cm}{4cm}}{\pgfpoint{5cm}{0cm}}{\pgfpoint{5cm}{4cm}}
+% \pgfgetpath\temppath
+% \pgfsetstrokecolor{red}
+% \pgfusepath{stroke}
+%
+% \pgfset{decoration text={Here is some text all the way along this curve!}}
+% \pgfdecoration{{text}{\pgfdecoratedremainingdistance}}
+% \pgfsetpath\temppath
+% \endpgfdecoration
+% \endpgfpicture
+%
+\def\pgfdecoration#1{%
+ \begingroup%
+ \def\pgf@decorate@decorationlist{#1}%
+ \pgf@decoration@env%
+}%
+
+\def\endpgfdecoration{%
+ \pgf@decoration@endenv%
+ \ifx\pgfdecoratedpath\pgfutil@empty%
+ \else%
+ %
+ % Perform the decoration(s).
+ %
+ \pgf@decorate@for\pgf@temp:=\pgf@decorate@decorationlist\do{%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \expandafter\pgf@decorate@invoke\expandafter{\pgf@temp}%
+ \fi%
+ }%
+ \fi%
+ \pgfgetpath\pgfdecorationpath%
+ %
+ % Take stuff outside the group.
+ %
+ \global\let\pgf@decorate@decorationpathtemp\pgfdecorationpath%
+ \global\let\pgf@decorate@decoratedpathtemp\pgfdecoratedpath%
+ \global\let\pgf@decorate@existingpathtemp\pgfdecorateexistingpath%
+ \global\let\pgfpoint@decorated@pathlasttemp\pgfpoint@decorated@pathlast%
+ \endgroup%
+ %
+ % Are we in LaTeX?
+ %
+ \pgfutil@ifnextchar\@checkend{\aftergroup\pgf@decorate@installmacrosatend}%
+ {\pgf@decorate@installmacrosatend}%
+}%
+
+
+
+% Environment \pgfmetadecoration \endpgfmetadecoration
+%
+% Decorate a path with decoration automatons!
+%
+% Example:
+%
+% \pgfdeclaremetadecoration{fancy line}{line to}{
+% \state{line to}[width=1cm, next state=zigzag]
+% {
+% \decoration{lineto}
+% \beforedecoration{\pgfpathmoveto{\pgfpointdecoratedpathfirst}}
+% \afterdecoration
+% {
+% \pgfsetstrokecolor{black}
+% \pgfusepath{stroke}
+% }
+% }
+% \state{zigzag}[width=2cm, next state=line to]
+% {
+% \decoration{zigzag}
+% \beforedecoration{\pgfpathmoveto{\pgfpointdecoratedpathfirst}}
+% \afterdecoration
+% {
+% \pgfsetstrokecolor{red}
+% \pgfusepath{stroke}
+% }
+% }
+% \state{final}
+% {
+% \decoration{lineto}
+% \beforedecoration{\pgfpathmoveto{\pgfpointdecoratedpathfirst}}
+% \afterdecoration
+% {
+% \pgfsetstrokecolor{black}
+% \pgfusepath{stroke}
+% }
+% }
+% }
+%
+% \pgfpicture
+% \pgfmetadecoration{fancy line}
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathcurveto{\pgfqpoint{0cm}{2cm}}{\pgfqpoint{3cm}{2cm}}{\pgfqpoint{3cm}{0cm}}
+% \pgfpathcurveto{\pgfqpoint{3cm}{-3cm}}{\pgfqpoint{0cm}{0cm}}{\pgfqpoint{0cm}{-3cm}}
+% \pgfpathcurveto{\pgfqpoint{0cm}{-5cm}}{\pgfqpoint{3cm}{-5cm}}{\pgfqpoint{3cm}{-3cm}}
+% \endpgfmetadecoration
+% \endpgfpicture
+%
+\def\pgfmetadecoration#1{%
+ \begingroup%
+ \let\decoration\pgf@metadecoration@decoration%
+ \let\beforedecoration\pgf@metadecoration@beforedecoration%
+ \let\afterdecoration\pgf@metadecoration@afterdecoration%
+ \def\pgf@metadecoration@name{#1}%
+ \pgf@decoration@env%
+}%
+
+\def\endpgfmetadecoration{%
+ \pgf@decoration@endenv%
+ \ifx\pgfdecoratedpath\pgfutil@empty%
+ \else%
+ \let\pgfmetadecoratedpathlength\pgf@decorate@totalpathlength%
+ \def\pgfmetadecoratedinputsegmentremainingdistance{\pgfdecoratedremainingdistance}%
+ \def\pgfmetadecoratedinputsegmentcompleteddistance{\pgfdecoratedcompleteddistance}%
+ %
+ % Perform the meta decoration...
+ %
+ \expandafter\let\expandafter\pgf@metadecoration@current@state%
+ \csname pgf@metadecoration@@\pgf@metadecoration@name @initial\endcsname%
+ \pgf@metadecoration@run%
+ %
+ % ..until the final state.
+ %
+ \let\pgf@decorate@tempname\pgfutil@empty%
+ \let\pgf@decorate@tempbefore\pgfutil@empty%
+ \let\pgf@decorate@tempafter\pgfutil@empty%
+ \csname pgf@metadecoration@@\pgf@metadecoration@name @\pgf@metadecoration@current@state @code\endcsname%
+ \ifx\pgf@decorate@tempname\pgfutil@empty%
+ \def\pgf@decorate@tempname{moveto}
+ \fi%
+ \pgf@decorate@invoke{%
+ {\pgf@decorate@tempname}{\pgfdecoratedremainingdistance}%
+ {\pgf@decorate@tempbefore}{\pgf@decorate@tempafter}%
+ }%
+ \fi%
+ \pgfgetpath\pgfdecorationpath%
+ %
+ % Take stuff outside the group.
+ %
+ \global\let\pgf@decorate@decorationpathtemp\pgfdecorationpath%
+ \global\let\pgf@decorate@decoratedpathtemp\pgfdecoratedpath%
+ \global\let\pgf@decorate@existingpathtemp\pgfdecorateexistingpath%
+ \global\let\pgfpoint@decorated@pathlasttemp\pgfpoint@decorated@pathlast%
+ \endgroup%
+ %
+ % Are we in LaTeX?
+ %
+ \pgfutil@ifnextchar\@checkend{\aftergroup\pgf@decorate@installmacrosatend}%
+ {\pgf@decorate@installmacrosatend}%
+}%
+
+
+
+
+
+
+% Internal macro for the decoration environment.
+%
+\def\pgf@decoration@env{%
+ \pgfgetpath\pgfdecorateexistingpath%
+ \pgfsetpath\pgfutil@empty%
+ \let\pgfdecorationpath\pgfutil@empty%
+ \let\pgfdecoratedpath\pgfutil@empty%
+ \let\pgfpoint@decorated@pathlast\pgfpointorigin%
+ \edef\pgfpoint@decorate@existingpathlast{\pgf@x\the\pgf@path@lastx\pgf@y\the\pgf@path@lasty}%
+ %
+ % Begin a group so transformations don't mess things up.
+ %
+ \bgroup%
+}%
+
+\def\pgf@decorate@path@check@moveto#1{%
+ \expandafter\pgf@decorate@path@@check@moveto#1\pgf@decorate@stop\pgf@decorate@@stop}%
+
+\def\pgf@decorate@token@stop{\pgf@decorate@stop}%
+\def\pgf@decorate@path@@check@moveto#1#2#3#4\pgf@decorate@@stop#5#6{%
+ \def\pgf@decorate@temp{#4}%
+ \pgf@x=#2\relax%
+ \pgf@y=#3\relax%
+ \ifx\pgf@decorate@temp\pgf@decorate@token@stop%
+ #5%
+ \else%
+ #6%
+ \fi%
+}%
+
+\def\pgf@decoration@endenv{%
+ \egroup%
+ \pgftransformreset%
+ %
+ % Save the existing soft path and restore the existing path.
+ %
+ \pgfgetpath\pgfdecoratedpath%
+ \pgfsetpath\pgfdecorateexistingpath%
+ %
+ \ifx\pgfdecoratedpath\pgfutil@empty%
+ \pgferror{I cannot decorate an empty path}%
+ \else%
+ %
+ % If the path consists of a single moveto token, make it
+ % a very small horizontal line.
+ %
+ \pgf@decorate@path@check@moveto\pgfdecoratedpath{%
+ \advance\pgf@x by0.0001pt\relax%
+ \edef\pgfdecoratedpath{%
+ \expandafter\noexpand\pgfdecoratedpath%
+ \noexpand\pgfsyssoftpath@linetotoken{\the\pgf@x}{\the\pgf@y}%
+ }%
+ }%
+ {}%
+ %
+ % Remove special round tokens and get points.
+ %
+ \pgfprocessround{\pgfdecoratedpath}{\pgfdecoratedpath}%
+ %
+ % Parse the soft path into a series of decorated input segment objects.
+ %
+ \pgf@decorate@parsesoftpath{\pgfdecoratedpath}{\pgf@decorate@inputsegmentobjects}%
+ %
+ % Setup further options
+ %
+ \pgfkeys{/pgf/every decoration/.try}%
+ %
+ % Reverse objects if necessary.
+ %
+ \ifpgf@decorate@inputsegmentobjects@reverse%
+ \pgf@decorate@inputsegmentobjects@reverse{\pgf@decorate@inputsegmentobjects}{\pgf@decorate@inputsegmentobjects}%
+ \fi%
+ %
+ \let\pgf@decorated@remainingdistance\pgf@decorate@totalpathlength%
+ %
+ \let\pgfpoint@decorated@totalpathfirst\pgfpoint@decorated@firstparsed%
+ \let\pgfpoint@decorated@totalpathlast\pgfpoint@decorate@lastnonmovetoparsed%
+ %
+ \let\pgfpoint@decorated@pathfirst\pgfpoint@decorated@totalpathfirst
+ \let\pgfpoint@decorated@pathlast\pgfpoint@decorated@totalpathlast%
+ %
+ % Set up the first input segment.
+ %
+ \let\pgf@decorate@currentinputsegmentobjects\pgf@decorate@inputsegmentobjects%
+ \let\pgf@decorate@transformtoinputsegment\pgfutil@empty%
+ \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject%
+ \pgf@decorate@processnextinputsegmentobject%
+ \pgf@decorate@distancetomove0pt\relax%
+ \fi%
+}%
+
+
+
+
+\def\pgf@decorate@installmacrosatend{%
+ \let\pgfdecorationpath\pgf@decorate@decorationpathtemp%
+ \let\pgfdecoratedpath\pgf@decorate@decoratedpathtemp%
+ \let\pgfdecorateexistingpath\pgf@decorate@existingpathtemp%
+ \let\pgfpoint@decorated@pathlast\pgfpoint@decorated@pathlasttemp%
+}%
+
+\let\pgfdecorationpath\pgfutil@empty
+\let\pgfdecoratedpath\pgfutil@empty
+\let\pgfdecorateexisitingpath\pgfutil@empty
+
+\let\pgfpoint@decorated@pathlast\pgfpointorigin
+
+
+
+% A version of \pgfutil@for which doesn't expand each value in #3.
+%
+\def\pgf@decorate@for#1:=#2\do#3{%
+ \def\pgf@decorate@for@var{#1}%
+ \def\pgf@decorate@for@action{#3}%
+ \expandafter\pgf@decorate@@for#2,\pgf@stop,}%
+
+\def\pgf@decorate@@for#1,{%
+ \ifx#1\pgf@stop%
+ \expandafter\let\pgf@decorate@for@var\pgfutil@empty%
+ \else%
+ \expandafter\def\pgf@decorate@for@var{#1}%
+ \pgf@decorate@for@action%
+ \expandafter\pgf@decorate@@for%
+ \fi%
+}%
+
+
+% Invoke a decoration.
+%
+% #1 - {<name>}{<distance>}{<before code>}{<after code>}
+%
+\def\pgf@decorate@invoke#1{%
+ \pgf@decorate@@invoke#1\pgf@decorate@invoke\pgf@decorate@invoke\pgf@decorate@invoke\pgf@stop}%
+
+\def\pgf@decorate@@invoke#1#2#3#4#5\pgf@stop{%
+ \pgfutil@ifundefined{pgf@decorate@@#1@initial}%
+ {%
+ \pgferror{Unknown decoration `#1'}%
+ }%
+ {%
+ \def\pgf@decorate@name{#1}%
+ \ifx\pgf@decorate@invoke#3%
+ \let\pgf@decorate@beforecode\pgfutil@empty%
+ \else%
+ \def\pgf@decorate@beforecode{#3}%
+ \fi%
+ \ifx\pgf@decorate@invoke#4%
+ \let\pgf@decorate@aftercode\pgfutil@empty%
+ \else%
+ \def\pgf@decorate@aftercode{#4}%
+ \fi%
+ %
+ % Make remaining distance and the decorated path length `public'.
+ %
+ \pgfdecoratedremainingdistance\pgf@decorated@remainingdistance\relax%
+ \let\pgfdecoratedpathlength\pgf@decorate@totalpathlength%
+ %
+ \pgfmathsetlength\pgf@xa{#2}%
+ \ifdim\pgf@xa>\pgf@decorated@remainingdistance\relax%
+ \pgf@xa\pgf@decorated@remainingdistance\relax%
+ \fi%
+ \edef\pgf@decorate@currentpathlength{\the\pgf@xa}%
+ %
+ % Calculate the distance remaining to the end of the entire path.
+ %
+ \pgf@xa-\pgf@decorate@currentpathlength\relax%
+ \advance\pgf@xa\pgf@decorated@remainingdistance\relax%
+ \edef\pgf@decorated@remainingdistance{\the\pgf@xa}%
+ %
+ % Set up the macros and distances for the current section
+ % of the decorated path.
+ %
+ \let\pgfdecoratedpathlength\pgf@decorate@currentpathlength%
+ \pgfdecoratedremainingdistance\pgfdecoratedpathlength\relax%
+ \pgfdecoratedcompleteddistance0pt\relax%
+ %
+ % Execute user-defined code beore decoration.
+ %
+ \pgf@decorate@beforecode%
+ %
+ % Run the decoration...
+ %
+ \expandafter\let\expandafter\pgf@decorate@current@state%
+ \csname pgf@decorate@@\pgf@decorate@name @initial\endcsname%
+ \pgf@decorate@run%
+ %
+ % ...until the final state.
+ %
+ \ifdim\pgf@decorated@remainingdistance<1pt\relax% Should be =0pt, but need to control for inaccuracies.
+ \let\pgfpoint@decorated@pathlast\pgfpoint@decorated@totalpathlast%
+ \else%
+ %
+ % Set up \pgfpoint@decorated@pathlast if the end of
+ % the total decorated path has not been reached.
+ %
+ {%
+ \pgf@decorate@movealonginputsegment{\the\pgfdecoratedremainingdistance}%
+ \pgf@decorate@transformtoinputsegment%
+ \pgfpointorigin%
+ \pgf@pos@transform@glob%
+ \global\pgf@x\pgf@x%
+ \global\pgf@y\pgf@y%
+ }%
+ \edef\pgfpoint@decorated@pathlast{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}%
+ \fi%
+ {%
+ \pgftransformreset%
+ \pgf@decorate@transformtoinputsegment%
+ \pgf@decorate@additionaltransform%
+ \csname pgf@decorate@@\pgf@decorate@name @final@code\endcsname%
+ }%
+ \pgf@decorate@movealonginputsegment{\the\pgfdecoratedremainingdistance}%
+ %
+ % Execute user-defined code after decoration.
+ %
+ \pgf@decorate@aftercode%
+ %
+ % Update the input segment objects.
+ %
+ \let\pgf@decorate@additionaltransform\pgfutil@empty%
+ \let\pgf@decorate@inputsegmentobjects\pgf@decorate@inputsegmentobjects@aftersplit%
+ \let\pgfpoint@decorated@pathfirst\pgfpoint@decorated@pathlast%
+ }%
+}%
+
+
+
+\let\pgf@decorate@transformtoinputsegment\pgfutil@empty%
+\let\pgf@decorate@additionaltransform\pgfutil@empty%
+
+
+% \pgfpointdecoratedpathfirst
+%
+\def\pgfpointdecoratedpathfirst{%
+ {%
+ \pgftransforminvert%
+ \pgfpoint@decorated@pathfirst%
+ \pgf@pos@transform@glob%
+ \global\pgf@x\pgf@x%
+ \global\pgf@y\pgf@y%
+ }%
+}%
+
+% \pgfpointdecoratedpathlast
+%
+\def\pgfpointdecoratedpathlast{%
+ {%
+ \pgftransforminvert%
+ \pgfpoint@decorated@pathlast%
+ \pgf@pos@transform@glob%
+ \global\pgf@x\pgf@x%
+ \global\pgf@y\pgf@y%
+ }%
+}%
+
+% \pgfpointdecoratedinputsegmentfirst
+%
+% The first point of the current sub-path.
+%
+\def\pgfpointdecoratedinputsegmentfirst{%
+ {%
+ \pgftransforminvert%
+ \pgf@decorate@inputsegment@first%
+ \pgf@pos@transform@glob%
+ \global\pgf@x\pgf@x%
+ \global\pgf@y\pgf@y%
+ }%
+}%
+
+% \pgfpointdecoratedinputsegmentlast
+%
+% The final point of the current sub-path.
+%
+\def\pgfpointdecoratedinputsegmentlast{%
+ {%
+ \pgftransforminvert%
+ \pgf@decorate@inputsegment@last%
+ \pgf@pos@transform@glob%
+ \global\pgf@x\pgf@x%
+ \global\pgf@y\pgf@y%
+ }%
+}%
+
+
+\def\pgf@final@text{final}%
+
+% Run a normal decoration.
+%
+\def\pgf@decorate@run{%
+ \let\pgf@decorate@next\pgf@decorate@do@state%
+ \ifx\pgf@decorate@current@state\pgf@final@text%
+ \let\pgf@decorate@next\relax%
+ \fi%
+ \pgf@decorate@next%
+}%
+
+\def\pgf@decorate@do@state{%
+ \let\pgf@decorate@next\relax%
+ \let\pgf@decorate@next@state\pgf@decorate@current@state%
+ %
+ % Get the options.
+ %
+ \let\pgf@decorate@persistent@pre=\relax%
+ \let\pgf@decorate@persistent@post=\relax%
+ \expandafter\expandafter\expandafter\pgf@decorate@setter
+ \expandafter\expandafter\expandafter{\csname pgf@decorate@@\pgf@decorate@name @\pgf@decorate@current@state @options\endcsname}%
+ \ifx\pgf@decorate@next\relax%
+ \let\pgf@decorate@next\pgf@decorate@do@code%
+ \fi%
+ \pgf@decorate@next%
+}%
+
+\def\pgf@decorate@setter{\pgfqkeys{/pgf/decoration automaton}}%
+
+\pgf@decorate@repeatstate-1\relax
+
+\def\pgf@decorate@do@code{%
+ %
+ % Execute code.
+ %
+ \pgf@decorate@persistent@pre%
+ {%
+ \pgftransformreset%
+ \pgf@decorate@transformtoinputsegment%
+ \pgf@decorate@additionaltransform%
+ \csname pgf@decorate@@\pgf@decorate@name @\pgf@decorate@current@state @code\endcsname%
+ }%
+ \pgf@decorate@persistent@post%
+ \pgf@decorate@movealongpath{\pgf@decorate@width}%
+ %
+ % Next iteration.
+ %
+ \ifnum\pgf@decorate@repeatstate>0\relax%
+ \advance\pgf@decorate@repeatstate-1\relax%
+ \else%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@current@state\pgf@decorate@next@state%
+ \fi%
+ \pgf@decorate@run%
+}%
+
+\pgfkeys{
+ /pgf/decoration automaton/width/.code=\def\pgf@decorate@width{#1}\pgf@decorate@switch@if#1 to final\pgf@stop,%
+ /pgf/decoration automaton/switch if less than/.code=\pgf@decorate@switch@if#1\pgf@stop,%
+ /pgf/decoration automaton/switch if input segment less than/.code=\pgf@decorate@switch@ifinputsegment#1\pgf@stop,%
+ /pgf/decoration automaton/next state/.store in=\pgf@decorate@next@state,%
+ /pgf/decoration automaton/persistent precomputation/.store in=\pgf@decorate@persistent@pre,%
+ /pgf/decoration automaton/persistent postcomputation/.store in=\pgf@decorate@persistent@post,%
+ /pgf/decoration automaton/repeat state/.code={%
+ \ifnum\pgf@decorate@repeatstate=-1\relax%
+ \pgfmathsetcount\pgf@decorate@repeatstate{#1}%
+ \fi%
+ },%
+ /pgf/decoration automaton/if input segment is closepath/.code={%
+ \ifpgf@decorate@is@closepath@%
+ \pgfkeysalso{#1}%
+ \fi%
+ },
+ /pgf/decoration automaton/auto end on length/.code=\pgf@decorate@auto@end{#1},
+ /pgf/decoration automaton/auto corner on length/.code=\pgf@decorate@auto@corner{#1},
+}%
+
+\def\pgf@decorate@auto@end#1{%
+ \ifx\pgf@decorate@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifpgf@decorate@is@closepath@%
+ \ifdim\pgfdecoratedremainingdistance>\pgf@x%
+ \ifdim\pgfdecoratedinputsegmentremainingdistance>\pgf@x%
+ \else%
+ \pgfpathclose%
+ \pgf@decorate@movealongpath{\pgfdecoratedinputsegmentremainingdistance}%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \else%
+ \pgfpathclose%
+ \def\pgf@decorate@current@state{final}%
+ \def\pgf@decorate@width{\pgfdecoratedremainingdistance}
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \else%
+ \ifdim\pgfdecoratedremainingdistance>\pgf@x%
+ \else%
+ {%
+ \pgftransformreset%
+ \pgf@decorate@transformtoinputsegment%
+ \pgf@decorate@additionaltransform%
+ \pgfpathlineto{\pgfpoint{\pgfdecoratedremainingdistance}{0pt}}
+ }%
+ \def\pgf@decorate@current@state{final}%
+ \def\pgf@decorate@width{\pgfdecoratedremainingdistance}
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@decorate@auto@corner#1{%
+ \ifpgfdecoratepathhascorners%
+ \ifx\pgf@decorate@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgfdecoratedinputsegmentremainingdistance>\pgf@x%
+ \else%
+ {%
+ \pgftransformreset%
+ \pgf@decorate@transformtoinputsegment%
+ \pgf@decorate@additionaltransform%
+ \pgfpathlineto{\pgfqpoint{\pgfdecoratedinputsegmentremainingdistance}{0pt}}
+ }%
+ \pgf@decorate@movealongpath{\pgfdecoratedinputsegmentremainingdistance}%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@decorate@switch@if#1to #2\pgf@stop{%
+ \ifx\pgf@decorate@next\relax%
+ \ifdim\pgfdecoratedremainingdistance=0pt\relax%
+ \def\pgf@decorate@current@state{#2}%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \else%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgfdecoratedremainingdistance<\pgf@x%
+ \def\pgf@decorate@current@state{#2}%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@decorate@switch@ifinputsegment#1to #2\pgf@stop{%
+ \ifx\pgf@decorate@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgfdecoratedinputsegmentremainingdistance<\pgf@x%
+ \def\pgf@decorate@current@state{#2}%
+ \pgf@decorate@repeatstate-1\relax%
+ \let\pgf@decorate@next\pgf@decorate@run%
+ \fi%
+ \fi%
+}%
+
+
+
+
+% \pgfsetdecorationsegmenttransformation
+%
+% Set the additional transform for each decoration state.
+%
+% Example:
+%
+% \pgfsetdecorationsegmenttransformation{\pgftransformyshift{5pt}}
+%
+\def\pgfsetdecorationsegmenttransformation#1{\def\pgf@decorate@additionaltransform{#1}}%
+\let\pgf@decorate@additionaltransform\pgfutil@empty%
+
+
+
+
+\def\pgf@metadecoration@decoration#1{%
+ \edef\pgf@decorate@tempname{#1}%
+}%
+\def\pgf@metadecoration@beforedecoration#1{%
+ \def\pgf@decorate@tempbefore{#1}%
+}%
+\def\pgf@metadecoration@afterdecoration#1{%
+ \def\pgf@decorate@tempafter{#1}%
+}%
+
+
+\def\pgf@final@text{final}%
+
+% Run a meta decoration.
+%
+\def\pgf@metadecoration@run{%
+ \let\pgf@metadecoration@next\pgf@metadecoration@do@state%
+ \ifx\pgf@metadecoration@current@state\pgf@final@text%
+ \let\pgf@metadecoration@next\relax%
+ \fi%
+ \pgf@metadecoration@next%
+}%
+
+\def\pgf@metadecoration@do@state{%
+ \let\pgf@metadecoration@next\relax%
+ \let\pgf@metadecoration@next@state\pgf@metadecoration@current@state%
+ %
+ % Set up some macros.
+ %
+ \let\pgfmetadecoratedremainingdistance\pgf@decorated@remainingdistance%
+ \pgf@x-\pgfmetadecoratedremainingdistance\relax%
+ \advance\pgf@x\pgf@decorate@totalpathlength\relax%
+ \edef\pgfmetadecoratedcompleteddistance{\the\pgf@x}%
+ %
+ % Get the options.
+ %
+ \expandafter\expandafter\expandafter\pgf@metadecoration@setter
+ \expandafter\expandafter\expandafter{\csname pgf@metadecoration@@\pgf@metadecoration@name @\pgf@metadecoration@current@state @options\endcsname}%
+ \ifx\pgf@metadecoration@next\relax%
+ \let\pgf@metadecoration@next\pgf@metadecoration@do@code%
+ \fi%
+ \pgf@metadecoration@next%
+}%
+
+\def\pgf@metadecoration@do@code{%
+ %
+ % Execute code.
+ %
+ \let\pgf@decorate@tempname\pgfutil@empty%
+ \let\pgf@decorate@tempbefore\pgfutil@empty%
+ \let\pgf@decorate@tempafter\pgfutil@empty%
+ \let\pgfpointmetadecoratedpathfirst\pgfpointdecoratedpathfirst%
+ \let\pgfpointmetadecoratedpathlast\pgfpointdecoratedpathlast%
+ \csname pgf@metadecoration@@\pgf@metadecoration@name @\pgf@metadecoration@current@state @code\endcsname%
+ \ifx\pgf@decorate@tempname\pgfutil@empty%
+ \def\pgf@decorate@tempname{moveto}
+ \fi%
+ \pgf@decorate@invoke{%
+ {\pgf@decorate@tempname}{\pgf@metadecoration@width}%
+ {\pgf@decorate@tempbefore}{\pgf@decorate@tempafter}%
+ }%
+ %
+ % Next iteration.
+ %
+ \let\pgf@metadecoration@current@state\pgf@metadecoration@next@state%
+ \pgf@metadecoration@run%
+}%
+
+\def\pgf@metadecoration@setter{\pgfqkeys{/pgf/meta-decoration automaton}}%
+
+\pgfkeys{
+ /pgf/meta-decoration automaton/width/.code=\def\pgf@metadecoration@width{#1}\pgf@metadecoration@switch@if#1 to final\pgf@stop,%
+ /pgf/meta-decoration automaton/switch if less than/.code=\pgf@metadecoration@switch@if#1\pgf@stop,%
+ /pgf/meta-decoration automaton/switch if input segment less than/.code=\pgf@metadecoration@switch@ifinputsegment#1\pgf@stop,%
+ /pgf/meta-decoration automaton/next state/.store in=\pgf@metadecoration@next@state,%
+}%
+
+\def\pgf@metadecoration@switch@if#1to #2\pgf@stop{%
+ \ifx\pgf@metadecoration@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgf@decorated@remainingdistance<\pgf@x%
+ \def\pgf@metadecoration@current@state{#2}%
+ \let\pgf@metadecoration@next\pgf@metadecoration@run%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@metadecoration@switch@ifinputsegment#1to #2\pgf@stop{%
+ \ifx\pgf@metadecoration@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgfdecoratedinputsegmentremainingdistance<\pgf@x%
+ \def\pgf@metadecoration@current@state{#2}%
+ \let\pgf@metadecoration@next\pgf@metadecoration@run%
+ \fi%
+ \fi%
+}%
+
+
+
+% Move along the path by a specified distance.
+%
+\def\pgf@decorate@movealongpath#1{%
+ \pgfmathsetlength\pgf@decorate@distancetomove{#1}%
+ \advance\pgfdecoratedcompleteddistance\pgf@decorate@distancetomove%
+ \advance\pgfdecoratedremainingdistance-\pgf@decorate@distancetomove%
+ \pgf@decorate@@movealongpath%
+}%
+\def\pgf@decorate@@movealongpath{%
+ \advance\pgfdecoratedinputsegmentcompleteddistance\pgf@decorate@distancetomove%
+ \advance\pgfdecoratedinputsegmentremainingdistance-\pgf@decorate@distancetomove%
+ \ifdim\pgfdecoratedinputsegmentremainingdistance>0pt\relax%
+ \let\pgf@next\pgf@decorate@@@movealongpath%
+ \else%
+ \pgf@decorate@distancetomove-\pgfdecoratedinputsegmentremainingdistance%
+ \pgf@decorate@processnextinputsegmentobject%
+ \ifx\pgf@decorate@currentinputsegmentobjects\pgfutil@empty%
+ \pgfdecoratedremainingdistance0pt\relax%
+ \let\pgf@next\relax%
+ \else%
+ \let\pgf@next\pgf@decorate@@movealongpath%
+ \fi%
+ \fi%
+ \pgf@next%
+}%
+
+\def\pgf@decorate@@@movealongpath{%
+ %
+ % Move along input segment for real.
+ %
+ \pgf@decorate@movealonginputsegment{\the\pgf@decorate@distancetomove}%
+ \pgf@decorate@distancetomove0pt\relax%
+ %
+ % Grrr. Hacking to control some inaccuracies.
+ %
+ \ifdim\pgf@decorate@inputsegmenttime pt>1pt\relax%
+ \let\pgf@decorate@inputsegmenttimetemp\pgf@decorate@inputsegmenttime%
+ \pgf@decorate@processnextinputsegmentobject%
+ \pgf@x\pgf@decorate@inputsegmenttimetemp pt\relax%
+ \advance\pgf@x-1pt\relax%
+ \edef\pgf@decorate@inputsegmenttime{\pgfmath@tonumber{\pgf@x}}%
+ \ifx\pgf@decorate@currentinputsegmentobjects\pgfutil@empty%
+ \pgfdecoratedremainingdistance0pt\relax%
+ \fi%
+ \fi%
+}%
+
+% Return the next input segment object in a macro
+%
+\def\pgf@decorate@getnextinputsegmentobject#1{%
+ \ifx\pgf@decorate@currentinputsegmentobjects\pgfutil@empty%
+ \let\pgf@next\relax%
+ \else%
+ \def\pgf@decorate@temp{#1}%
+ \let\pgf@next\pgf@decorate@@getnextinputsegmentobject%
+ \fi%
+ \pgf@next%
+}%
+\def\pgf@decorate@@getnextinputsegmentobject{%
+ \expandafter\pgf@decorate@@@getnextinputsegmentobject\pgf@decorate@currentinputsegmentobjects\pgf@stop}%
+\def\pgf@decorate@@@getnextinputsegmentobject#1#2\pgf@stop{%
+ \expandafter\def\pgf@decorate@temp{#1}%
+ \def\pgf@decorate@currentinputsegmentobjects{#2}}%
+
+% Process the next input segment object.
+%
+\def\pgf@decorate@processnextinputsegmentobject{%
+ \let\pgfdecorationpreviousinputsegment\pgfdecoratecurrentinputsegment%
+ \let\pgf@decorate@currentinputsegmentobject\pgf@decorate@nextinputsegmentobject%
+ \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject%
+ %
+ % If the current input segment object is a moveto, execute the
+ % object macro and get the next input segment object.
+ %
+ \pgf@decorate@is@closepath@false%
+ \pgf@decorate@currentinputsegmentobject%
+ \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto%
+ \pgfpathmoveto{\pgf@decorate@inputsegment@first}%
+ \let\pgfdecorationpreviousinputsegment\pgfdecorationcurrentinputsegment%
+ \let\pgf@decorate@currentinputsegmentobject\pgf@decorate@nextinputsegmentobject%
+ \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject%
+ \pgf@decorate@is@closepath@false%
+ \pgf@decorate@currentinputsegmentobject%
+ \fi%
+ %
+ % Teensy hack in case a path goes nowhere.
+ %
+ \ifdim\pgfdecoratedinputsegmentlength=0pt\relax%
+ \def\pgfdecoratedinputsegmentlength{0.05pt}% Arbitrary choice >0pt.
+ \fi%
+ \pgfdecoratedinputsegmentremainingdistance\pgfdecoratedinputsegmentlength\relax%
+ \pgfdecoratedinputsegmentcompleteddistance0pt\relax%
+ \def\pgf@decorate@inputsegmenttime{0}%
+ %
+ % Get the angle at the start of the input segment.
+ %
+ \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto%
+ \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ \let\pgfdecoratedangle\pgfmathresult%
+ \let\pgfdecoratedinputsegmentstartangle\pgfmathresult%
+ \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
+ \let\pgfdecoratedinputsegmentendangle\pgfmathresult%
+ \else%
+ \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@last}%
+ \let\pgfdecoratedangle\pgfmathresult%
+ \let\pgfdecoratedinputsegmentstartangle\pgfmathresult%
+ \let\pgfdecoratedinputsegmentendangle\pgfmathresult%
+ \fi%
+ %
+ % Get the angle to the next input segment.
+ %
+ \begingroup%
+ \pgf@decorate@nextinputsegmentobject%
+ \global\let\pgf@decorate@temp\pgfdecorationcurrentinputsegment%
+ \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto%
+ \expandafter\pgf@decorate@currentinputsegmentobject%
+ \fi%
+ \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto%
+ \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ \else%
+ \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@last}%
+ \fi%
+ \pgf@x-\pgfdecoratedangle pt\relax%
+ \advance\pgf@x\pgfmathresult pt\relax%
+ \edef\pgfdecoratedangletonextinputsegment{\the\pgf@x}%
+ \pgfmath@smuggleone\pgfdecoratedangletonextinputsegment%
+ \endgroup%
+ \let\pgfdecorationnextinputsegmentobject\pgf@decorate@temp%
+}%
+
+
+%
+% Input segment objects
+%
+
+\newif\ifpgf@decorate@is@closepath@%
+
+% Input segment types.
+%
+% These allow comparison with \ifx using
+%
+% \pgfdecorationcurrentinputsegment
+% \pgfdecorationnextinputsegment
+% \pgfdecorationcurrentprevioussegment
+%
+\def\pgfdecorationinputsegmentmoveto{moveto}%
+\def\pgfdecorationinputsegmentlineto{lineto}%
+\def\pgfdecorationinputsegmentcurveto{curveto}%
+\def\pgfdecorationinputsegmentclosepath{closepath}%
+\def\pgfdecorationinputsegmentlast{last}%
+
+% Input segment object moveto.
+%
+\def\pgf@decorate@inputsegmentobject@moveto#1{%
+ \def\pgf@decorate@inputsegment@first{#1}%
+ \def\pgf@decorate@inputsegment@supporta{#1}%
+ \def\pgf@decorate@inputsegment@supportb{#1}%
+ \def\pgf@decorate@inputsegment@last{#1}%
+ \edef\pgf@decorate@lastmoveto{#1}%
+ \def\pgfdecoratedinputsegmentlength{0pt}%
+ \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto%
+}%
+
+% Input segment object lineto.
+%
+\def\pgf@decorate@inputsegmentobject@lineto#1#2#3{%
+ \def\pgfdecoratedinputsegmentlength{#1}%
+ \def\pgf@decorate@inputsegment@first{#2}%
+ \def\pgf@decorate@inputsegment@last{#3}%
+ %
+ % Supports should be defined like this, so if treated as a curve,
+ % equal time steps will correspond to equal distances.
+ %
+ \pgfpointdiff{#2}{#3}%
+ \pgf@xa\pgf@x%
+ \pgf@ya\pgf@y%
+ \pgfextract@process\pgf@decorate@inputsegment@supporta{%
+ \pgf@process{#2}%
+ \advance\pgf@x0.333333\pgf@xa%
+ \advance\pgf@y0.333333\pgf@ya%
+ }%
+ \pgfextract@process\pgf@decorate@inputsegment@supportb{%
+ \pgf@process{#2}%
+ \advance\pgf@x0.666666\pgf@xa%
+ \advance\pgf@y0.666666\pgf@ya%
+ }%
+ \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@line%
+ \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@line%
+ \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentlineto%
+}%
+
+% Input segment object curveto.
+%
+\def\pgf@decorate@inputsegmentobject@curveto#1#2#3#4#5{%
+ \def\pgfdecoratedinputsegmentlength{#1}%
+ \def\pgf@decorate@inputsegment@first{#2}%
+ \def\pgf@decorate@inputsegment@supporta{#3}%
+ \def\pgf@decorate@inputsegment@supportb{#4}%
+ \def\pgf@decorate@inputsegment@last{#5}%
+ %
+ \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@curve%
+ \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@curve%
+ \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto%
+}%
+
+% Input segment object closepath.
+%
+% Treated like a lineto, but flag that it is a closepath.
+%
+\def\pgf@decorate@inputsegmentobject@closepath#1#2#3{%
+ \pgf@decorate@is@closepath@true%
+ %
+ \def\pgfdecoratedinputsegmentlength{#1}%
+ \def\pgf@decorate@inputsegment@first{#2}%
+ \def\pgf@decorate@inputsegment@last{#3}%
+ %
+ \pgfpointdiff{#2}{#3}%
+ \pgf@xa\pgf@x%
+ \pgf@ya\pgf@y%
+ \pgfextract@process\pgf@decorate@inputsegment@supporta{%
+ \pgf@process{#2}%
+ \advance\pgf@x0.333333\pgf@xa%
+ \advance\pgf@y0.333333\pgf@ya%
+ }%
+ \pgfextract@process\pgf@decorate@inputsegment@supportb{%
+ \pgf@process{#2}%
+ \advance\pgf@x0.666666\pgf@xa%
+ \advance\pgf@y0.666666\pgf@ya%
+ }%
+ %
+ \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@line%
+ \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@line%
+ \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentclosepath%
+}%
+
+
+% Input segment object endofinputsegments.
+%
+\def\pgf@decorate@inputsegmentobject@endofinputsegments{%
+ \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentlast%
+}%
+
+
+
+
+% This macro controls how the automaton moves along a line sub-path
+%
+\def\pgf@decorate@movealonginputsegment@line#1{}% Nothing special needed.
+
+% This macro controls how the automaton moves along a curve sub-path.
+%
+\def\pgf@decorate@movealonginputsegment@curve#1{%
+ \ifdim#1=0pt\relax%
+ \else%
+ \pgfpointcurveattime{\pgf@decorate@inputsegmenttime}%
+ {\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ {\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
+ \pgf@xa\pgf@x%
+ \pgf@ya\pgf@y%
+ \pgf@xb\pgf@decorate@inputsegmenttime pt\relax%
+ %
+ % Reduce the initial time step, depending on the length
+ % of the path. To do: Optimise this step (should also depend on #1).
+ %
+ \ifdim\pgf@decorate@currentpathlength<128pt\relax%
+ \pgf@yb.03125pt\relax%
+ \else%
+ \ifdim\pgf@decorate@currentpathlength<512pt\relax%
+ \pgf@yb.015625pt\relax%
+ \else%
+ \ifdim\pgf@decorate@currentpathlength<2048pt\relax%
+ \pgf@yb.00390625pt\relax%
+ \else%
+ \pgf@yb.0009765625pt\relax%
+ \fi%
+ \fi%
+ \fi%
+ \c@pgf@counta1\relax%
+ \pgfutil@tempdima0pt\relax%
+ \pgfmathloop%
+ \advance\pgf@xb\c@pgf@counta\pgf@yb%
+ %
+ % We would like to use \pgfpointcurveattime. However, we must not
+ % overuse \pgf@process or \pgfmath stuff within this loop,
+ % otherwise we increase the chances of save stack overflow.
+ %
+ \edef\pgf@decorate@temp{%
+ \pgf@xa\the\pgf@xa%
+ \pgf@xb\the\pgf@xb%
+ \pgf@ya\the\pgf@ya%
+ \pgf@yb\the\pgf@yb%
+ }%
+ %
+ \pgfpoint@decorate@curveattime{\pgfmath@tonumber{\pgf@xb}}%
+ {\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ {\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
+ \pgf@decorate@temp%
+ %
+ \pgf@xc\pgf@xa%
+ \pgf@yc\pgf@ya%
+ \pgf@xa\pgf@x%
+ \pgf@ya\pgf@y%
+ \advance\pgf@x-\pgf@xc%
+ \advance\pgf@y-\pgf@yc%
+ \pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}%
+ \pgfutil@tempdimb\pgfmathresult pt\relax%
+ \advance\pgfutil@tempdima\c@pgf@counta\pgfutil@tempdimb%
+ \ifnum\c@pgf@counta>0\relax%
+ \ifdim\pgfutil@tempdima>#1\relax%
+ \c@pgf@counta-\c@pgf@counta%
+ \pgf@yb.5\pgf@yb%
+ \fi%
+ \else%
+ \ifdim\pgfutil@tempdima<#1\relax%
+ \c@pgf@counta-\c@pgf@counta%
+ \pgf@yb.5\pgf@yb%
+ \fi%
+ \fi%
+ \ifdim\pgf@yb=0pt\relax% *Should* be OK.
+ \else%
+ \repeatpgfmathloop%
+ \edef\pgf@decorate@inputsegmenttime{\pgfmath@tonumber{\pgf@xb}}%
+ %
+ % Now calculate the angle at the new time on the curve.
+ %
+ % We can use \pgfpointcurveattime safely here.
+ %
+ \pgfpointcurveattime{\pgf@decorate@inputsegmenttime}%
+ {\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ {\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
+ \edef\pgf@marshal{%
+ \noexpand\pgfmathanglebetweenpoints%
+ {\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb}%
+ {\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}%
+ }%
+ \pgf@marshal%
+ \let\pgfdecoratedangle\pgfmathresult%
+ \fi%
+}%
+
+% \pgfpoint@decorate@curveattime
+%
+% A `quick' version of \pgfpointcurveattime
+%
+% No parsing and no use of \pgf@process.
+% This prevents save stack build up when used inside a loop.
+%
+\def\pgfpoint@decorate@curveattime#1#2#3#4#5{%
+ \edef\pgf@time@s{#1}%
+ \pgf@x-\pgf@time@s pt\relax%
+ \advance\pgf@x1pt\relax%
+ \edef\pgf@time@t{\pgf@sys@tonumber{\pgf@x}}%
+ #5\relax%
+ \pgf@xc=\pgf@x%
+ \pgf@yc=\pgf@y%
+ #4\relax%
+ \pgf@xb=\pgf@x%
+ \pgf@yb=\pgf@y%
+ #3\relax%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ #2\relax%
+ % First iteration:
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+ \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
+ \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
+ \pgf@xb=\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc%
+ \pgf@yb=\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc%
+ % Second iteration:
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+ \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
+ \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
+ % Save x/y
+ \pgf@xb=\pgf@x%
+ \pgf@yb=\pgf@y%
+ % Third iteration:
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+}%
+
+
+% Applies the necessary transform for a line sub-path.
+%
+\def\pgf@decorate@transformtoinputsegment@line{%
+ \pgftransformshift{%
+ \pgfpointlineatdistance{\pgfdecoratedinputsegmentcompleteddistance}{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@last}
+ }%
+ \pgftransformrotate{\pgfdecoratedangle}%
+}%
+
+% Applies the necessary transform for a curve sub-path.
+%
+\def\pgf@decorate@transformtoinputsegment@curve{%
+ \pgfslopedattimetrue%
+ \pgfallowupsidedownattimetrue%
+ \pgftransformcurveattime{\pgf@decorate@inputsegmenttime}%
+ {\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
+ {\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
+}%
+
+
+
+
+
+% \pgf@decorate@parsesoftpath
+%
+% Parses an instance of a soft path into intermediate line and curve
+% sub-path objects which the decoration automaton can use to traverse
+% the decorated path.
+%
+% The soft path should be well formed and only contain `primative'
+% soft path tokens, that is: moveto, lineto, curvetosupporta,
+% curvetosupportb, curveto, rectcorner, rectsize, and closepath.
+% (i.e., all specialround tokens should have removed using
+% \pgfprocessround)
+%
+% The overall length of the path is also calculated and returned
+% in the macro \pgfdecoratedpathlength.
+%
+% Parameters:
+%
+% #1 - a macro containing a well formed soft path.
+% #2 - a macro to store the intermediate sub-path representations.
+%
+% Example:
+%
+% \pgfpathmoveto{\pgfpointorigin}
+% \pgfpathlineto{\pgfpoint{0pt}{12pt}}
+% \pgfpathlineto{\pgfpoint{12pt}{0pt}}
+% \pgfgetpath\softpath
+%
+% \pgf@decorate@parsesoftpath{\softpath}{\parsedsoftpath}
+%
+% results in:
+%
+% \parsedsoftpath ->
+% {\pgf@decorate@inputsegmentobject@lineto{12pt}{\pgf@x 0pt\pgf@y 0pt}{\pgf@x 0pt\pgf@y 12pt}}
+% {\pgf@decorate@inputsegmentobject@lineto{12pt}{\pgf@x 0pt\pgf@y 12pt}{\pgf@x 12pt\pgf@y 12pt}}
+%
+% \pgfdecoratedpathlength ->
+% 24pt
+%
+
+\def\pgf@decorate@parsesoftpath#1#2{%
+ \def\pgf@decorate@inputsegmentobjectsmacro{#2}%
+ \let\pgf@decorate@inputsegmentobjects\pgfutil@empty%
+ \pgfutil@tempdima0pt\relax%
+ \let\pgfpoint@decorate@lastparsed\pgfpoint@decorate@existingpathlast%
+ \let\pgfpoint@decorate@lastnonmovetoparsed\pgfpoint@origin%
+ \let\pgf@decorate@queueinputsegmentobject\pgfutil@empty%
+ \let\pgfpoint@decorated@firstparsed\pgfutil@empty%
+ \expandafter\pgf@decorate@@parsesoftpath#1\pgf@stop%
+}%
+
+\def\pgf@decorate@@parsesoftpath#1{%
+ \ifx#1\pgf@stop%
+ \let\pgf@decorate@queueinputsegmentobject\pgfutil@empty% <- removes final moveto (may not be desirable).
+ \pgf@decorate@addtoinputsegmentobjects{\pgf@decorate@inputsegmentobject@endofinputsegments}%
+ \pgf@decorate@addtoinputsegmentobjects{\pgf@decorate@inputsegmentobject@endofinputsegments}%
+ \expandafter\let\pgf@decorate@inputsegmentobjectsmacro\pgf@decorate@inputsegmentobjects%
+ \edef\pgf@decorate@totalpathlength{\the\pgfutil@tempdima}%
+ \let\pgf@next\relax%
+ \else%
+ \ifx#1\pgfsyssoftpath@movetotoken%
+ \let\pgf@next\pgf@decorate@parsemoveto%
+ \else%
+ \ifx#1\pgfsyssoftpath@linetotoken%
+ \let\pgf@next\pgf@decorate@parselineto%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetosupportatoken%
+ \let\pgf@next\pgf@decorate@parsecurveto%
+ \else%
+ \ifx#1\pgfsyssoftpath@closepathtoken%
+ \let\pgf@next\pgf@decorate@parseclosepath%
+ \else%
+ \ifx#1\pgfsyssoftpath@rectcornertoken%
+ \let\pgf@next\pgf@decorate@parserect%
+ \else%
+ \pgferror{Unrecognised soft path token `#1'}%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \pgf@next}%
+
+
+\def\pgf@decorate@addtoinputsegmentobjects#1{%
+ %
+ % If there is an input segment object waiting (i.e. a moveto), insert it here.
+ %
+ \ifx\pgf@decorate@queueinputsegmentobject\pgfutil@empty%
+ \else%
+ \let\pgf@decorate@temp\pgf@decorate@queueinputsegmentobject%
+ \let\pgf@decorate@queueinputsegmentobject\pgfutil@empty%
+ \expandafter\pgf@decorate@addtoinputsegmentobjects\expandafter{\pgf@decorate@temp}%
+ \fi%
+ \ifx\pgfpoint@decorated@firstparsed\pgfutil@empty%
+ #1%
+ \let\pgfpoint@decorated@firstparsed\pgf@decorate@inputsegment@first%
+ \fi%
+ \expandafter\def\expandafter\pgf@decorate@inputsegmentobjects\expandafter%
+ {\pgf@decorate@inputsegmentobjects{#1}}%
+}%
+
+% Convert \pgfsyssoftpath@movetotoken{<X>}{<Y>} into the following
+% representation:
+%
+% \pgf@decorate@inputsegmentobject@moveto{\pgf@x X\pgf@y Y}
+%
+% The moveto input segment object is not added immediately, so that
+% only the last of multiple movetos is inserted.
+%
+\def\pgf@decorate@parsemoveto#1#2{%
+ \def\pgf@decorate@queueinputsegmentobject{\pgf@decorate@inputsegmentobject@moveto{\pgf@x#1\pgf@y#2}}%
+ \def\pgfpoint@decorate@lastparsed{\pgf@x#1\pgf@y#2}%
+ \pgf@decorate@@parsesoftpath%
+}%
+
+% Convert \pgfsyssoftpath@linetotoken{<X>}{<Y>} into the following
+% representation:
+%
+% \pgf@decorate@inputsegmentobject@lineto{<length>}{\pgf@x <Last X> \pgf@y <Last Y}{\pgf@x <X> \pgf@y <Y>}
+%
+\def\pgf@decorate@parselineto#1#2{%
+ \pgf@decorate@linelength{\pgfpoint@decorate@lastparsed}{\pgf@x#1\pgf@y#2}%
+ \advance\pgfutil@tempdima\pgfmathresult pt\relax%
+ \edef\pgf@decorate@temp{%
+ \noexpand\pgf@decorate@inputsegmentobject@lineto{\pgfmathresult pt}{\pgfpoint@decorate@lastparsed}{\pgf@x#1\pgf@y#2}%
+ }%
+ \edef\pgfpoint@decorate@lastparsed{\pgf@x#1\pgf@y#2}%
+ \let\pgfpoint@decorate@lastnonmovetoparsed\pgfpoint@decorate@lastparsed%
+ \expandafter\pgf@decorate@addtoinputsegmentobjects\expandafter{\pgf@decorate@temp}%
+ \pgf@decorate@@parsesoftpath%
+}%
+
+% Convert \pgfsyssoftpath@curvetosupportatoken{<Xa>}{<Ya>}...etc
+% into the following representation:
+%
+% \pgf@decorate@inputsegmentobject@curveto{<length>}{\pgf@x <Last X> \pgf@y <Last Y}
+% {\pgf@x <Xa> \pgf@y <Ya>}{\pgf@x <Xb> \pgf@y <Yb>}{\pgf@x <X> \pgf@y <Y>}
+%
+\def\pgf@decorate@parsecurveto#1#2\pgfsyssoftpath@curvetosupportbtoken#3#4\pgfsyssoftpath@curvetotoken#5#6{%
+ \pgf@decorate@curvelength{\pgfpoint@decorate@lastparsed}{\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
+ \advance\pgfutil@tempdima\pgfmathresult pt\relax%
+ \edef\pgf@decorate@temp{%
+ \noexpand\pgf@decorate@inputsegmentobject@curveto{\pgfmathresult pt}{\pgfpoint@decorate@lastparsed}%
+ {\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
+ }%
+ \expandafter\pgf@decorate@addtoinputsegmentobjects\expandafter{\pgf@decorate@temp}%
+ \edef\pgfpoint@decorate@lastparsed{\pgf@x#5\pgf@y#6}%
+ \let\pgfpoint@decorate@lastnonmovetoparsed\pgfpoint@decorate@lastparsed%
+ \pgf@decorate@@parsesoftpath%
+}%
+
+
+\def\pgf@decorate@parseclosepath#1#2{%
+ \pgf@decorate@linelength{\pgfpoint@decorate@lastparsed}{\pgf@x#1\pgf@y#2}%
+ \advance\pgfutil@tempdima\pgfmathresult pt\relax%
+ \edef\pgf@decorate@temp{%
+ \noexpand\pgf@decorate@inputsegmentobject@closepath{\pgfmathresult pt}{\pgfpoint@decorate@lastparsed}{\pgf@x#1\pgf@y#2}%
+ }%
+ \expandafter\pgf@decorate@addtoinputsegmentobjects\expandafter{\pgf@decorate@temp}%
+ \edef\pgfpoint@decorate@lastparsed{\pgf@x#1\pgf@y#2}%
+ \let\pgfpoint@decorate@lastnonmovetoparsed\pgfpoint@decorate@lastparsed%
+ \pgf@decorate@@parsesoftpath%
+}%
+
+% Convert \pgfsyssoftpath@rectcornertoken{<X>}{<Y>}\pgfsyssoftpath@rectsizetoken{<Xa>}{<Ya>}
+% into either (clockwise)
+%
+% \pgf@decorate@inputsegmentobject@moveto{<X>}{<Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 1>}{\pgf@x <X> \pgf@y <Y>}{\pgf@x <X> \pgf@y <Ya+Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 2>}{\pgf@x <X> \pgf@y <Ya+Y>}{\pgf@x <Xa+X> \pgf@y <Ya+Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 1>}{\pgf@x <Xa+X> \pgf@y <Ya+X>}{\pgf@x <Xa+X> \pgf@y <Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 2>}{\pgf@x <Xa+X> \pgf@y <Y>}{\pgf@x <X> \pgf@y <Y>}
+% \pgf@decorate@inputsegmentobject@moveto{<Xa>}{<Ya>}
+%
+% ...or (anti-clockwise)
+%
+% \pgf@decorate@inputsegmentobject@moveto{<X>}{<Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 2>}{\pgf@x <X> \pgf@y <Y>}{\pgf@x <Xa+X> \pgf@y <Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 1>}{\pgf@x <Xa+X> \pgf@y <Y>}{\pgf@x <Xa+X> \pgf@y <Ya+Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 2>}{\pgf@x <Xa+X> \pgf@y <Ya+Y>}{\pgf@x <X> \pgf@y <Ya+Y>}
+% \pgf@decorate@inputsegmentobject@lineto{<length 1>}{\pgf@x <X> \pgf@y <Ya+Y>}{\pgf@x <X> \pgf@y <Y>}
+% \pgf@decorate@inputsegmentobject@moveto{<Xa>}{<Ya>}
+%
+\newif\ifpgfdecoraterectangleclockwise
+\def\pgf@decorate@parserect#1#2\pgfsyssoftpath@rectsizetoken#3#4{%
+ %
+ % Subvert \pgf@decorate@parsesoftpath so parsing macros will
+ % return here instead of continuing to parse the soft path.
+ %
+ \let\pgf@decorate@orig@@parsesoftpath\pgf@decorate@@parsesoftpath%
+ \let\pgf@decorate@@parsesoftpath\relax%
+ \pgf@decorate@parsemoveto{#1}{#2}%
+ \pgf@xa#1\relax%
+ \pgf@ya#2\relax%
+ \ifpgfdecoraterectangleclockwise%
+ \advance\pgf@ya#4%
+ \pgf@yb\pgf@ya%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@xa#3%
+ \pgf@xb\pgf@xa%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@ya-#4%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@xa-#3%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parseclosepath\pgf@temp%
+ \else%
+ \advance\pgf@xa#3%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \pgf@xb\pgf@xa%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@ya#4%
+ \pgf@yb\pgf@ya%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@xa-#3%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parselineto\pgf@temp%
+ \advance\pgf@ya-#4%
+ \edef\pgf@temp{{\the\pgf@xa}{\the\pgf@ya}}%
+ \expandafter\pgf@decorate@parseclosepath\pgf@temp%
+ \fi%
+ %
+ % Restore the parsing.
+ %
+ \let\pgf@decorate@@parsesoftpath\pgf@decorate@orig@@parsesoftpath%
+ \edef\pgf@marshal{\noexpand\pgf@decorate@parsemoveto{\the\pgf@xb}{\the\pgf@yb}}%
+ \pgf@marshal%
+}%
+
+
+
+
+% \pgf@decorate@linelength
+%
+% Define \pgfmathresult as the distance between #1 and #2 (without units).
+%
+\def\pgf@decorate@linelength#1#2{%
+ \pgf@process{\pgfpointdiff{#1}{#2}}%
+ \pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}%
+}%
+
+% \pgf@decorate@curvelength
+%
+% Define \pgfmathresult as the length (without units) of the cubic
+% bezier described by #1,#2,#3 and #4.
+%
+% To approximate the length of the curve P (sort of) use:
+%
+% curveLength(P,q)
+% Q = subdivideLeft(P);
+% R = subdivideRight(P);
+% return curveLength'(Q,q) + curveLength'(R,q);
+%
+% curveLength'(P,q)
+% <P1,P2,P3,P4> <- P;
+% P' = P4 - P1;
+% x = P'.x();
+% y = P'.y();
+% if (x < q) && (y < q)
+% return |P'|;
+% else%
+% Q = subdivideLeft(P);
+% R = subdivideRight(P);
+% return curveLength'(Q,q) + curveLength'(R,q);
+%
+% Where q is some small value (`tolerance').
+%
+\newif\ifpgf@decorate@subdivide
+\def\pgf@decorate@curvelength#1#2#3#4{%
+ %
+ % Always begin with a subdivision in case #1 = #4.
+ %
+ \begingroup%
+ \pgf@decorate@recursive@subdividecurve@left{#1}{#2}{#3}{#4}%
+ \pgfutil@tempdimb\pgfmathresult pt\relax%
+ \pgf@decorate@recursive@subdividecurve@right{#1}{#2}{#3}{#4}%
+ \advance\pgfutil@tempdimb\pgfmathresult pt\relax%
+ \pgfmath@returnone\pgfutil@tempdimb%
+ \endgroup%
+}%
+
+\def\pgf@decorate@@curvelength#1#2#3#4{%
+ \begingroup%
+ \pgf@decorate@curvecordlength{#1}{#2}{#3}{#4}%
+ \ifpgf@decorate@subdivide%
+ \pgf@decorate@recursive@subdividecurve@left{#1}{#2}{#3}{#4}%
+ \pgfutil@tempdimb\pgfmathresult pt\relax%
+ \pgf@decorate@recursive@subdividecurve@right{#1}{#2}{#3}{#4}%
+ \advance\pgfutil@tempdimb\pgfmathresult pt\relax%
+ \expandafter\pgfmath@returnone\expandafter\pgfutil@tempdimb%
+ \else%
+ \expandafter\pgfmath@returnone\expandafter\pgfmathresult\expandafter p\expandafter t\expandafter%
+ \fi%
+ \endgroup%
+}%
+
+\def\pgf@decorate@curvelength@tolerance{1pt}%
+
+\def\pgf@decorate@curvecordlength#1#2#3#4{%
+ %
+ % Calculate the curve cord vector.
+ %
+ #4\relax%
+ \pgf@xa\pgf@x\pgf@ya\pgf@y%
+ #1\relax%
+ \advance\pgf@xa-\pgf@x%
+ \advance\pgf@ya-\pgf@y%
+ \ifdim\pgf@xa<0pt\relax\pgf@xa-\pgf@xa\fi%
+ \ifdim\pgf@ya<0pt\relax\pgf@ya-\pgf@ya\fi%
+ %
+ % Always subdivide, unless...
+ %
+ \pgf@decorate@subdividetrue%
+ %
+ % The cord vector is small.
+ %
+ \ifdim\pgf@xa<\pgf@decorate@curvelength@tolerance\relax%
+ \ifdim\pgf@ya<\pgf@decorate@curvelength@tolerance\relax%
+ \pgfmathveclen@{\pgfmath@tonumber{\pgf@xa}}{\pgfmath@tonumber{\pgf@ya}}%
+ \pgf@decorate@subdividefalse%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@decorate@recursive@subdividecurve@left#1#2#3#4{%
+ {%
+ %
+ % The left curve (from t=0 to t=.5)
+ %
+ #1\relax%
+ \pgfutil@tempdima\pgf@x%
+ \pgfutil@tempdimb\pgf@y%
+ \pgf@xa.5\pgf@x\pgf@ya.5\pgf@y%
+ \pgf@xb.25\pgf@x\pgf@yb.25\pgf@y%
+ \pgf@xc.125\pgf@x\pgf@yc.125\pgf@y%
+ #2\relax%
+ \advance\pgf@xa.5\pgf@x\advance\pgf@ya.5\pgf@y%
+ \advance\pgf@xb.5\pgf@x\advance\pgf@yb.5\pgf@y%
+ \advance\pgf@xc.375\pgf@x\advance\pgf@yc.375\pgf@y%
+ #3\relax%
+ \advance\pgf@xb.25\pgf@x\advance\pgf@yb.25\pgf@y%
+ \advance\pgf@xc.375\pgf@x\advance\pgf@yc.375\pgf@y%
+ #4\relax%
+ \advance\pgf@xc.125\pgf@x\advance\pgf@yc.125\pgf@y%
+ \xdef\pgf@marshal{%
+ \noexpand\pgf@decorate@@curvelength%
+ {\pgf@x\the\pgfutil@tempdima\pgf@y\the\pgfutil@tempdimb}%
+ {\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}{\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb}
+ {\pgf@x\the\pgf@xc\pgf@y\the\pgf@yc}%
+ }%
+ }%
+ \pgf@marshal%
+}%
+
+\def\pgf@decorate@recursive@subdividecurve@right#1#2#3#4{%
+ {%
+ %
+ % The right curve (from t=0.5 to t=1)
+ %
+ #1\relax%
+ \pgfutil@tempdima.125\pgf@x\pgfutil@tempdimb.125\pgf@y%
+ #2\relax%
+ \advance\pgfutil@tempdima.375\pgf@x\advance\pgfutil@tempdimb.375\pgf@y%
+ \pgf@xa.25\pgf@x\pgf@ya.25\pgf@y%
+ #3\relax%
+ \advance\pgfutil@tempdima.375\pgf@x\advance\pgfutil@tempdimb.375\pgf@y%
+ \advance\pgf@xa.5\pgf@x\advance\pgf@ya.5\pgf@y%
+ \pgf@xb.5\pgf@x\pgf@yb.5\pgf@y%
+ #4\relax%
+ \advance\pgfutil@tempdima.125\pgf@x\advance\pgfutil@tempdimb.125\pgf@y%
+ \advance\pgf@xa.25\pgf@x\advance\pgf@ya.25\pgf@y%
+ \advance\pgf@xb.5\pgf@x\advance\pgf@yb.5\pgf@y%
+ \pgf@xc\pgf@x\pgf@yc\pgf@y%
+ \xdef\pgf@marshal{%
+ \noexpand\pgf@decorate@@curvelength%
+ {\pgf@x\the\pgfutil@tempdima\pgf@y\the\pgfutil@tempdimb}%
+ {\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}{\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb}
+ {\pgf@x\the\pgf@xc\pgf@y\the\pgf@yc}%
+ }%
+ }%
+ \pgf@marshal%
+}%
+
+
+% Macro to reverse a set of input segment objects.
+%
+% #1 - a macro holding the input segment objects.
+% #2 - a macro holding the reversed input segment objects.
+%
+\def\pgf@decorate@inputsegmentobjects@reverse#1#2{%
+ \def\pgf@decorate@path@storein{#2}%
+ \def\pgf@decorate@inputsegments@@temp{}%
+ \expandafter\pgf@decorate@inputsegments@@reverse@pass@first#1\pgf@stop}%
+
+\def\pgf@decorate@inputsegments@@reverse@pass@first#1#2\pgf@stop{%
+ \def\pgf@decorate@temp{#1}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter%
+ \pgf@decorate@inputsegments@@temp\expandafter\expandafter\expandafter%
+ {\expandafter\pgf@decorate@temp\pgf@decorate@inputsegments@@temp}%
+ \def\pgf@decorate@test{#2}
+ \ifx\pgf@decorate@test\pgfutil@empty%
+ \def\pgf@decorate@next{%
+ \expandafter\pgf@decorate@inputsegmentobjects@reverse@pass@second\pgf@decorate@inputsegments@@temp\pgf@stop%
+ }%
+ \else%
+ \def\pgf@decorate@next{\pgf@decorate@inputsegments@@reverse@pass@first#2\pgf@stop}%
+ \fi%
+ \pgf@decorate@next%
+}%
+\def\pgf@decorate@inputsegmentobjects@reverse@pass@second#1#2#3\pgf@stop{%
+ \def\pgf@decorate@inputsegments@temp{#3}%
+ \def\pgf@decorate@inputsegments@@temp{}%
+ \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty
+ \let\pgf@decorate@last@object=\pgfutil@empty
+ \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingtrue%
+ \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse%
+ \expandafter\pgf@decorate@path@@reverse@pass@second\pgf@decorate@inputsegments@temp\pgf@stop}%
+
+
+\def\pgf@decorate@path@@reverse@pass@second#1{%
+ \ifx#1\pgf@stop%
+ \expandafter\def\expandafter\pgf@decorate@inputsegments@@temp\expandafter{%
+ \pgf@decorate@inputsegments@@temp%
+ {\pgf@decorate@inputsegmentobject@endofinputsegments}%
+ {\pgf@decorate@inputsegmentobject@endofinputsegments}
+ }%
+ \expandafter\let\pgf@decorate@path@storein=\pgf@decorate@inputsegments@@temp%
+ \let\pgf@decorate@next=\relax%
+ \else%
+ \ifx#1\pgf@decorate@inputsegmentobject@moveto%
+ \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@moveto%
+ \else%
+ \ifx#1\pgf@decorate@inputsegmentobject@lineto%
+ \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@lineto%
+ \else%
+ \ifx#1\pgf@decorate@inputsegmentobject@curveto%
+ \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@curveto%
+ \else%
+ \ifx#1\pgf@decorate@inputsegmentobject@closepath%
+ \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@closepath%
+ \else%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \pgf@decorate@next%
+}%
+
+\newif\ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting
+
+\def\pgf@decorate@inputsegmentobjects@reverse@moveto#1{%
+ \ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting%
+ \edef\pgf@decorate@current@inputsegmentobject{%
+ {\noexpand\pgf@decorate@inputsegmentobject@closepath%
+ {\pgf@decorate@reverse@closepath@length}%
+ {\pgf@decorate@last}%
+ {#1}%
+ }%
+ }%
+ \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse%
+ \else%
+ \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty%
+ \fi%
+ \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingtrue%
+ \pgf@decorate@path@@@reverse@pass@second%
+}%
+
+\newif\ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting
+
+\def\pgf@decorate@inputsegmentobjects@reverse@closepath#1#2#3{%
+ \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingtrue%
+ \def\pgf@decorate@reverse@closepath@length{#1}%
+ \def\pgf@decorate@current@inputsegmentobject{}%
+ \pgf@decorate@inputsegmentobjects@reverse@lineto{#1}{#2}{#3}%
+}%
+
+\def\pgf@decorate@inputsegmentobjects@reverse@lineto#1#2#3#4{%
+ \ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting%
+ \def\pgf@decorate@current@inputsegmentobject{{\pgf@decorate@inputsegmentobject@moveto{#3}}}%
+ \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingfalse%
+ \else%
+ \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty%
+ \fi%
+ \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@lineto{#1}{#3}{#2}}}%
+ \ifx#4\pgf@decorate@inputsegmentobject@moveto%
+ \ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting%
+ \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@closepath{#1}{#3}{#2}}}%
+ \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse%
+ \else%
+ \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@lineto{#1}{#3}{#2}}}%
+ \fi%
+ \fi%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter%
+ \pgf@decorate@current@inputsegmentobject\expandafter\expandafter\expandafter%
+ {\expandafter\pgf@decorate@current@inputsegmentobject\pgf@decorate@append@inputsegmentobject}
+ \def\pgf@decorate@last{#2}%
+ \pgf@decorate@path@@@reverse@pass@second#4%
+}%
+
+\def\pgf@decorate@inputsegmentobjects@reverse@curveto#1#2#3#4#5{%
+ \ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting%
+ \def\pgf@decorate@current@inputsegmentobject{%
+ {\pgf@decorate@inputsegmentobject@moveto{#5}}%
+ {\pgf@decorate@inputsegmentobject@curveto{#1}{#5}{#4}{#3}{#2}}%
+ }%
+ \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingfalse%
+ \else%
+ \def\pgf@decorate@current@inputsegmentobject{{\pgf@decorate@inputsegmentobject@curveto{#1}{#5}{#4}{#3}{#2}}}%
+ \fi%
+ \def\pgf@decorate@last{#2}%
+ \pgf@decorate@path@@@reverse@pass@second%
+}%
+
+\def\pgf@decorate@path@@@reverse@pass@second{%
+ \ifx\pgf@decorate@current@inputsegmentobject\pgfutil@empty%
+ \else%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter%
+ \pgf@decorate@inputsegments@@temp\expandafter\expandafter\expandafter%
+ {\expandafter\pgf@decorate@inputsegments@@temp\pgf@decorate@current@inputsegmentobject}%
+ \fi%
+ \pgf@decorate@path@@reverse@pass@second%
+}%
+
+
+
+
+
+\let\startpgfdecoration=\pgfdecoration
+\let\stoppgfdecoration=\endpgfdecoration
+
+\let\startpgfmetadecoration=\pgfmetadecoration
+\let\stoppgfmetadecoration=\endpgfmetadecoration
+
+
+
+%
+% Predefined decorations
+%
+
+
+% Simple decorations.
+
+\pgfdeclaredecoration{lineto}{initial}{%
+ \state{initial}[switch if input segment less than=\pgfdecoratedremainingdistance to input segment,
+ width=\pgfdecoratedremainingdistance]
+ {
+ }%
+ \state{input segment}[width=\pgfdecoratedinputsegmentlength,next state=initial]
+ {
+ \pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
+ }%
+
+ \state{final}{\pgfpathlineto{\pgfpointdecoratedpathlast}}%
+}%
+
+\pgfdeclaredecoration{moveto}{initial}{%
+ \state{initial}[width=\pgfdecoratedremainingdistance]{}%
+ \state{final}{\pgfpathmoveto{\pgfpointdecoratedpathlast}}%
+}%
+
+% This decorations curves to the end along the line.
+
+\pgfdeclaredecoration{curveto}{initial}{%
+ \state{initial}[width=\pgfdecoratedinputsegmentlength/100]
+ {
+ \pgfpathlineto{\pgfpointorigin}
+ }%
+ \state{final}{\pgfpathlineto{\pgfpointdecoratedpathlast}}%
+}%
+
+
+
+
+% Compatibility with old "snakes":
+
+\let\pgfsnakeremainingdistance=\pgfdecoratedremainingdistance
+\let\pgfsnakecompleteddistance=\pgfdecoratedcompleteddistance
+\def\pgfsnakeangle{\pgfdecoratedangle}%
+\let\pgfdeclaresnake=\pgfdeclaredecoration
+\let\pgfsetsnakesegmenttransformation=\pgfsetdecorationsegmenttransformation
+\def\pgfpathsnakesto#1#2{%
+ \edef\pgf@temp{#1}%
+ \expandafter\pgfdecoration\expandafter{\pgf@temp}%
+ \pgfpathlineto{#2}%
+ \endpgfdecoration%
+}%
+\def\pgfpathsnaketo#1#2{\pgfpathsnakesto{{#1}{\pgfsnakeremainingdistance}}{#2}}%
+\def\pgfpathsnakealongvector#1#2#3{%
+ \pgf@process{#3}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgfmathparse{#2}%
+ \pgf@xa=\pgfmathresult\pgf@xa%
+ \pgf@ya=\pgfmathresult\pgf@ya%
+ \advance\pgf@xa by\pgf@path@lastx%
+ \advance\pgf@ya by\pgf@path@lasty%
+ \edef\pgf@snake@lib@temp{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
+ \pgfpathsnaketo{#1}{\pgf@snake@lib@temp}%
+}%
+
+\let\pgfsnakesegmentamplitude=\pgfdecorationsegmentamplitude
+\let\pgfsnakesegmentlength=\pgfdecorationsegmentlength
+\def\pgfsnakesegmentangle{\pgfdecorationsegmentangle}%
+\def\pgfsnakesegmentobjectlength{\pgfkeysvalueof{/pgf/decoration/shape start width}}%
+\def\pgfsnakesegmentaspect{\pgfdecorationsegmentaspect}%
+
+\pgfset{%
+ /pgf/segment amplitude/.style={/pgf/decoration={amplitude={#1},shape height={2*(#1)}}},
+ /pgf/segment length/.style={/pgf/decoration={segment length={#1}}},
+ /pgf/segment angle/.style={/pgf/decoration={angle={#1}}},
+ /pgf/segment aspect/.style={/pgf/decoration={aspect={#1}}},
+ /pgf/segment object length/.style={/pgf/decoration={shape width={#1},radius={#1}}}}%
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmodulematrix.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmodulematrix.code.tex
new file mode 100644
index 0000000000..166eb47093
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmodulematrix.code.tex
@@ -0,0 +1,660 @@
+% 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{pgfmodulematrix.code.tex}
+
+\usepgfmodule{shapes}%
+
+\newif\ifpgfmatrix
+\newif\ifpgf@matrix@correct@call
+
+\newif\ifpgf@matrix@fixed
+
+\newcount\pgfmatrixcurrentrow
+
+\newcount\pgfmatrixcurrentcolumn
+\newcount\pgf@matrix@numberofcolumns
+
+\let\pgf@matrix@cell=\pgfnodeparttextbox % alias
+\let\pgf@matrix@box=\pgf@matrix@cell % alias
+
+\long\def\pgfmatrixbeforeassemblenode#1{%
+ \long\def\pgf@matrix@before@assemnble@node{#1}}
+\pgfmatrixbeforeassemblenode{}
+
+% Sets the default row or column sep
+%
+% #1 = default row or column sep list
+%
+% Description:
+%
+% Sets the macro \pgfmatrixrowsep or \pgfmatrixcolumnsep to #1.
+%
+% Example:
+%
+% \pgfsetmatrixrowsep{5pt}
+
+\def\pgfsetmatrixrowsep#1{\def\pgfmatrixrowsep{#1}}%
+\def\pgfsetmatrixcolumnsep#1{\def\pgfmatrixcolumnsep{#1}}%
+
+\def\pgfmatrixrowsep{0pt}%
+\def\pgfmatrixcolumnsep{0pt}%
+
+
+
+% The pgfmatrix command creates a node that contains a matrix. Like
+% the \pgfnode command, it is to be used inside a pgfpicture
+% environment.
+%
+% #1 = shape type
+% #2 = anchor
+% #3 = name for later reference
+% #4 = path usage command
+% #5 = inner shift
+% #6 = startup code
+% #7 = the matrix code (may contain verbatim stuff)
+%
+% Description:
+%
+% This command creates a node that contains a matrix. For
+% each cell of the matrix, drawing commands may be given. These
+% commands will create a cell picture and a bounding box is computed
+% for each cell picture. The cell picture is then placed inside the
+% cell. The position inside the cell is computed according to the
+% following rules:
+%
+% 1. In each column, the origins of the cell pictures are all on a
+% vertical line.
+% 2. In each row, the origins of the cell pictures are all on a
+% horizontal line.
+% 3. All cells in the same row have the same height and depth.
+% 4. All cells in the same column have the same width.
+% 5. The size of cells are chosen minimal such that the boxes fit into
+% the cells and still meet the above requirement.
+%
+% Next, the whole resulting matrix, which is given as #7, is placed
+% inside a node whose name is given as #3, whose shape is #1, and
+% whose anchor is #2. This means that the resulting node is shifted
+% such that the given anchor lies at the origin. Then, as for a normal
+% node, the #4 path usage command is used for the node.
+%
+% The parameter #5 is an additional negative shift for the node. Normally, such
+% a shift could be given beforehand (that is, the shift could be
+% preapplied to the current transformation matrix). However, when #5
+% is evaluated, you can refer to temporary positions of nodes inside
+% the matrix. In detail, the following happens: When the matrix has
+% been typeset, all nodes in the matrix temporarily get assigned their
+% positions in the matrix box. The origin of this coordinate system is
+% at the left baseline end of the matrix box, which corresponds to the
+% text anchor. The position #5 is then interpreted inside this
+% coordinate system and then used for shifting.
+%
+% The idea behind using the parameter #5 is the following: If you
+% specify "text" as anchor #2 and specify \pgfpointanchor{inner
+% node}{some anchor} for parameter #5, where inner node is a node that
+% is created in the matrix, then the whole matrix will be shifted such
+% that inner node.some anchor lies at the origin of the whole picture.
+%
+% At the beginning and at the end of each cell, the macros
+% \pgfmatrixbegincode and \pgfmatrixendcode are called. Inside these
+% macros you can use \pgfmatrixcurrentcolumn and \pgfmatrixcurrentrow
+% to access the current row and column.
+%
+% Before each column except for the first, an extra space given by the
+% macro \pgfmatrixcolumnsep is added. Additionally, an extra space
+% given by the optional argument of the \pgfmatrixnextcell commands in
+% the first line are added, which may vary between columns. Between
+% rows, an extra space given by the macro \pgfmatrixrowsep is
+% added. You can also change this value for each row by using a \gdef.
+%
+%
+% Lines are ended using the command \pgfmatrixendrow. The command \\
+% is \let to be the same, but \\ is sometimes overridden by, say,
+% minipage, so it's good to have \pgfmatrixendrow as a "fallback".
+%
+% Inside the matrix, \\ must be used to end every line ***including
+% the last***. You can pass an optional parameter to \\ as in \\[2pt]
+% to give an additional space after this particular line.
+%
+% The usage of \\ at the end of the matrix is important since this
+% command is used to find the end of the matrix. What happens is that
+% \\ followed by a closing brace ends the matrix.
+%
+% Inside the matrix, you must use \pgfmatrixnextcell to separate
+% columns. The reason is that two columns are used internally for
+% every single column shown. The macro \pgfmatrixnextcell is yields
+% (more or less) two && (and some further trickery).
+%
+% The parameter #6 is executed at the beginning of the matrix
+% group. It is inside the protecting group of the matrix, but outside
+% the matrix itself. It can be used for different purposes: 1) It can be
+% used to simplify the next cell macro. 2) It can be used to issue an
+% \aftergroup command. 3) It can be used to setup local settings. For
+% example, by setting #6 to \let\&=\pgfmatrixnextcell you can use \&
+% instead of \pgfmatrixnextcell. You can also set the catcode of & to
+% active.
+%
+%
+% Example:
+%
+% \begin{tikzpicture}
+%
+% \draw (0,0) circle (1mm); % b.north will lie on the center of this circle
+%
+% \pgfmatrix{rectangle}{text}{mymatrix}{\pgfusepath{}}{\pgfpointanchor{b}{north}}{\let\&=\pgfmatrixnextcell}
+% {
+% \draw (0,0) circle (1cm); \& \node (a) [draw] {Hallo}; \\
+% \node (b) [draw] {Welt}; \& \draw (0,0) circle (5mm); \\
+% }
+%
+% \draw [->] (a) -- (b);
+%
+% \end{tikzpicture}
+
+\def\pgfmatrix#1#2#3#4#5#6{%
+ \ifpgfmatrix%
+ \pgferror{You cannot nest pgfmatrix environments, yet}
+ \fi%
+ \bgroup%
+ \everycr{}%
+ #6%
+ \def\pgf@matrix@par@shape{#1}%
+ \def\pgf@matrix@par@anchor{#2}%
+ \def\pgf@matrix@par@name{#3}%
+ \def\pgf@matrix@par@usage{#4}%
+ \def\pgf@matrix@par@shift{#5}%
+ % the matrix must have a name:
+ \ifx\pgf@matrix@par@name\pgfutil@empty%
+ \def\pgf@matrix@par@name{pgf@matrix@internal}%
+ \fi%
+ \pgfmatrixcurrentrow=0\relax%
+ \pgfmatrixcurrentcolumn=0\relax%
+ \pgf@matrix@numberofcolumns=0\relax%
+ \let\\=\pgfmatrixendrow%
+ \tabskip=0pt%
+ \offinterlineskip%
+ \pgfmatrixtrue%
+ \let\pgf@matrix@node@list=\pgfutil@empty%
+ \expandafter\let\csname pgf@matrix@column@finish@1\endcsname=\pgfutil@empty%
+ \let\pgf@matrix@row@finish=\pgfutil@empty%
+ %
+ % Get rid of bgroup
+ %
+ \afterassignment\pgf@matrix@cont\let\pgf@next=%
+}%
+\def\pgf@matrix@cont{%
+ \setbox\pgf@matrix@box=\hbox\bgroup\vbox\bgroup%
+ \halign\bgroup%
+ \pgf@matrix@init@row%
+ \pgf@matrix@step@column%
+ {%
+ \pgf@matrix@startcell%
+ ##%
+ \pgf@matrix@endcell%
+ }%
+ &%
+ ##\pgf@matrix@padding&&%
+ \pgf@matrix@step@column%
+ {%
+ \pgf@matrix@startcell%
+ ##%
+ \pgf@matrix@endcell%
+ }&%
+ ##\pgf@matrix@padding%
+ \cr%
+}%
+
+\def\pgf@end@matrix{%
+ \egroup\egroup%
+ \egroup%
+ %
+ % Inject custom tokens before assembling the node holding the matrix. Can
+ % be used to apply additional settings.
+ %
+ \pgf@matrix@before@assemnble@node
+ %
+ % If there are named nodes, we must adjust their coordinates.
+ %
+ \ifx\pgf@matrix@node@list\pgfutil@empty%
+ \else%
+ % Ok, this means we got a lot of work to do...
+ \pgf@matrix@compute@origin%
+ \pgf@matrix@shift@nodes@initial%
+ \fi%
+ %
+ % Compute additional shift
+ %
+ \pgftransformresetnontranslations%
+ \pgftransformshift{\pgf@process{\pgftransformreset\pgf@matrix@par@shift\pgf@x=-\pgf@x\pgf@y=-\pgf@y}}%
+ %
+ % Create node
+ %
+ \pgfmultipartnode{\pgf@matrix@par@shape}{\pgf@matrix@par@anchor}{\pgf@matrix@par@name}{\pgf@matrix@par@usage}%
+ %
+ % If there are named nodes, we must adjust their coordinates, again.
+ %
+ \ifx\pgf@matrix@node@list\pgfutil@empty%
+ \else%
+ {%
+ \pgftransformreset%
+ \pgf@process{\pgfpointanchor{\pgf@matrix@par@name}{text}}%
+ \xdef\pgf@matrix@offset{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
+ \pgf@matrix@shift@nodes@secondary{\pgf@matrix@offset}%
+ }%
+ \fi%
+}%
+
+
+
+
+% Ending a cell
+%
+% #1 = (optional) spacing between previous and next column. This
+% parameter only has an effect in the first row.
+%
+% Description:
+%
+% This command ends a cell of a matrix.
+%
+% Example:
+%
+% \pgfmatrix{rectangle}{text}{mymatrix}{\pgfusepath{}}{\pgfpointanchor{b}{north}}{}
+% {
+% \draw (0,0) circle (1cm); \pgfmatrixnextcell[1cm] \node (a) [draw] {Hallo}; \\
+% \node (b) [draw] {Welt}; \pgfmatrixnextcell \draw (0,0) circle (5mm); \\
+% }
+
+\def\pgfmatrixnextcell{%
+ % if the cell contains nothing, the following \let will be at the
+ % beginning (macro expansion has stopped here since neither \omit
+ % nor \span was found)
+ \let\pgf@matrix@signal@cell@end=\pgf@matrix@signal@cell@end%
+ \pgfutil@ifnextchar[{\pgf@matrix@cell@cont}{\pgf@matrix@cell@cont[0pt]}}%}%
+
+\def\pgf@matrix@cell@cont[#1]{%
+ \xdef\pgf@matrix@last@nextcell@options{#1}%
+ &\pgf@matrix@correct@calltrue&%
+}%
+
+
+\def\pgf@matrix@fixed@text{between origins}%
+\def\pgf@matrix@natural@text{between borders}%
+
+\def\pgf@matrix@addtolength#1#2{\edef\pgf@temp{#2}\expandafter\pgf@matrix@addtolength@\expandafter#1#2,\pgf@stop}%
+\def\pgf@matrix@addtolength@#1#2,#3\pgf@stop{%
+ \pgfkeys@spdef\pgf@temp{#2}%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \ifx\pgf@temp\pgf@matrix@fixed@text%
+ \global\pgf@matrix@fixedtrue%
+ \else%
+ \ifx\pgf@temp\pgf@matrix@natural@text%
+ \global\pgf@matrix@fixedfalse%
+ \else%
+ \pgfmathaddtolength{#1}{#2}%
+ \fi%
+ \fi%
+ \fi%
+ \def\pgf@temp{#3}%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \pgf@matrix@addtolength@#1#3\pgf@stop%
+ \fi%
+}%
+
+
+
+% Init a line
+
+\def\pgf@matrix@init@row{%
+ \relax%
+ \global\advance\pgfmatrixcurrentrow by 1\relax%
+ \global\pgfmatrixcurrentcolumn=0\relax%
+ \expandafter\gdef\csname pgf@matrix@maxy\the\pgfmatrixcurrentrow\endcsname{0pt}%
+ \expandafter\gdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{0pt}%
+}%
+
+
+
+% Step the row column number
+
+\def\pgf@matrix@step@column{%
+ \relax%
+ \global\advance\pgfmatrixcurrentcolumn by1\relax%
+}%
+
+
+
+% Start a cell
+
+\def\pgf@matrix@startcell{%
+ %
+ % Step 1: Init the list of nodes for this cell
+ %
+ \let\pgf@nodecallback=\pgf@matrix@nodecallback%
+ %
+ % Step 2: Setup the bounding box
+ %
+ \pgfinterruptboundingbox%
+ %
+ % Step 3: Reset the transformation matrix
+ %
+ \pgftransformreset%
+ %
+ % Step 4: Collect everything in a cell box
+ %
+ \setbox\pgf@matrix@cell=\hbox\bgroup\bgroup%
+ % make sure that cell pictures are not affected if matrices have
+ % 'overlay' option on:
+ \pgf@relevantforpicturesizetrue
+ \pgfsys@beginpicture%
+ \normalbaselines%
+ % Find out whether the cell is empty:
+ \pgfutil@ifnextchar\let%
+ {% ok, candidate, check following symbol
+ \afterassignment\pgf@matrix@empty@check\let\pgf@matrix@temp=% get rid of \let
+ }%
+ {% no, not empty
+ \pgf@matrix@empty@cell@false%
+ \pgfmatrixbegincode%
+ }%
+}%
+
+\def\pgf@matrix@empty@check{\futurelet\pgf@matrix@check@token\pgf@matrix@empty@check@cont}%
+\def\pgf@matrix@empty@check@cont{%
+ \ifx\pgf@matrix@check@token\pgf@matrix@signal@cell@end%
+ \pgf@matrix@empty@cell@true%
+ \expandafter%
+ \pgfmatrixemptycode%
+ \expandafter%
+ \let% reinserted
+ \else%
+ \pgf@matrix@empty@cell@false%
+ \expandafter%
+ \pgfmatrixbegincode%
+ \expandafter
+ \let% reinserted
+ \fi%
+}%
+
+\newif\ifpgf@matrix@empty@cell@
+
+
+% End a cell
+
+\def\pgf@matrix@endcell{%
+ \ifpgf@matrix@empty@cell@%
+ \else%
+ \expandafter\expandafter\expandafter\pgfmatrixendcode%
+ \expandafter\ifpgf@matrix@last@cell@in@row\expandafter\pgf@matrix@last@cell@in@rowtrue\expandafter\fi%
+ \fi%
+ \pgfsys@endpicture%
+ \ifnum\pgfmatrixcurrentcolumn<\pgf@matrix@numberofcolumns%
+ \else%
+ \ifpgf@matrix@last@cell@in@row\else%
+ {%
+ \global\pgf@matrix@fixedfalse%
+ \pgf@x=0pt%
+ \pgf@matrix@addtolength{\pgf@x}{\pgfmatrixcolumnsep}%
+ \pgf@matrix@addtolength{\pgf@x}{\pgf@matrix@last@nextcell@options}%
+ \ifpgf@matrix@fixed%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@matrix@column@finish@\the\pgfmatrixcurrentcolumn\endcsname%
+ {\global\pgf@picmaxx=0pt}%
+ \fi%
+ \advance\pgfmatrixcurrentcolumn by1\relax % only temporary for the following:
+ \expandafter\xdef\csname pgf@matrix@column@sep@\the\pgfmatrixcurrentcolumn\endcsname{\the\pgf@x}%
+ \ifpgf@matrix@fixed%
+ \expandafter\gdef\csname pgf@matrix@column@finish@\the\pgfmatrixcurrentcolumn\endcsname{\global\pgf@picminx=0pt}%
+ \else%
+ \expandafter\global\expandafter\let\csname pgf@matrix@column@finish@\the\pgfmatrixcurrentcolumn\endcsname=\pgfutil@empty%
+ \fi%
+ }%
+ \fi\fi%
+ % Special case of the empty picture
+ \ifdim\pgf@picmaxx=-16000pt\relax%
+ \global\pgf@picmaxx=0pt\relax%
+ \global\pgf@picminx=0pt\relax%
+ \global\pgf@picmaxy=0pt\relax%
+ \global\pgf@picminy=0pt\relax%
+ \fi%
+ \csname pgf@matrix@column@finish@\the\pgfmatrixcurrentcolumn\endcsname%
+ \pgf@matrix@row@finish%
+ \egroup\egroup%
+ %
+ % Step 5: Horizontal gap
+ %
+ \ifnum\pgfmatrixcurrentcolumn>1\relax%
+ \pgf@y=\csname pgf@matrix@column@sep@\the\pgfmatrixcurrentcolumn\endcsname\relax%
+ \advance\pgf@picminx by-\pgf@y%
+ \fi%
+ %
+ % Step 6: Protocol and adjust height and depth
+ %
+ % Step 6.1: Protocol...
+ %
+ \ifdim\pgf@picmaxy>\csname pgf@matrix@maxy\the\pgfmatrixcurrentrow\endcsname%
+ \expandafter\xdef\csname pgf@matrix@maxy\the\pgfmatrixcurrentrow\endcsname{\the\pgf@picmaxy}%
+ \fi%
+ \ifdim\pgf@picminy<\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname%
+ \expandafter\xdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{\the\pgf@picminy}%
+ \fi%
+ %
+ % Step 6.2: and setup.
+ %
+ \ht\pgf@matrix@cell=\pgf@picmaxy%
+ \dp\pgf@matrix@cell=-\pgf@picminy%
+ %
+ % Step 7: Protocol and adjust left and right width
+ %
+ % Step 7.1: Protocol...
+ %
+ \ifnum\pgfmatrixcurrentcolumn>\pgf@matrix@numberofcolumns\relax%
+ \expandafter\xdef\csname pgf@matrix@maxx\the\pgfmatrixcurrentcolumn\endcsname{\the\pgf@picmaxx}%
+ \expandafter\xdef\csname pgf@matrix@minx\the\pgfmatrixcurrentcolumn\endcsname{\the\pgf@picminx}%
+ \global\pgf@matrix@numberofcolumns=\pgfmatrixcurrentcolumn\relax%
+ \else%
+ \ifdim\pgf@picmaxx>\csname pgf@matrix@maxx\the\pgfmatrixcurrentcolumn\endcsname%
+ \expandafter\xdef\csname pgf@matrix@maxx\the\pgfmatrixcurrentcolumn\endcsname{\the\pgf@picmaxx}%
+ \fi%
+ \ifdim\pgf@picminx<\csname pgf@matrix@minx\the\pgfmatrixcurrentcolumn\endcsname%
+ \expandafter\xdef\csname pgf@matrix@minx\the\pgfmatrixcurrentcolumn\endcsname{\the\pgf@picminx}%
+ \fi%
+ \fi%
+ %
+ % Step 7.2: and setup.
+ %
+ \xdef\pgf@matrix@paddingskip{\the\pgf@picmaxx}%
+ %
+ % Step 8: Put in the box now
+ %
+ \hfil\hskip-\pgf@picminx%
+ \wd\pgf@matrix@cell=0pt%
+ \box\pgf@matrix@cell%
+ %
+ % Step 9: End bounding box
+ \endpgfinterruptboundingbox%
+}%
+
+% Default code for the start and end code
+\let\pgfmatrixbegincode=\relax
+\let\pgfmatrixendcode=\relax
+\let\pgfmatrixemptycode=\relax
+
+
+% The following callback is called for every node that is produced
+% inside a cell
+
+\def\pgf@matrix@nodecallback#1{%
+ \def\pgf@temp{#1}%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \xdef\pgf@matrix@node@list{\pgf@matrix@node@list,{#1}}%
+ \expandafter\xdef\csname pgf@matrix@node@location@#1\endcsname{{\the\pgfmatrixcurrentrow}{\the\pgfmatrixcurrentcolumn}}%
+ \fi%
+}%
+
+
+
+% Padding code
+
+\def\pgf@matrix@padding{%
+ \ifpgf@matrix@correct@call%
+ \else%
+ \pgferror{Single ampersand used with wrong catcode}%
+ \fi%
+ \hskip\pgf@matrix@paddingskip\hfil%
+}%
+
+
+% Compute the real positions of the origins
+
+% We must now compute the real positions of the origins of all the
+% small pictures. To this end, we need to compute prefix sums. After
+% the procedure is done, the minx and the maxy will contain the origin
+% positions.
+
+\def\pgf@matrix@compute@origin{%
+ %
+ % Inverse prefix sum on the vertical positions
+ %
+ {%
+ \ifnum\pgfmatrixcurrentrow>0\relax%
+ \expandafter\gdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{0pt}%
+ \fi
+ \c@pgf@counta=\pgfmatrixcurrentrow\relax%
+ \loop%
+ \ifnum\c@pgf@counta>1\relax%
+ \pgf@y=\csname pgf@matrix@miny\the\c@pgf@counta\endcsname\relax%
+ \advance\pgf@y by\csname pgf@matrix@maxy\the\c@pgf@counta\endcsname\relax
+ \advance\c@pgf@counta by-1\relax%
+ \pgf@ya=\csname pgf@matrix@miny\the\c@pgf@counta\endcsname\relax%
+ \advance\pgf@y by-\pgf@ya\relax%
+ \expandafter\xdef\csname pgf@matrix@miny\the\c@pgf@counta\endcsname{\the\pgf@y}%
+ \repeat%
+ }%
+ %
+ % Prefix sum on the horizontal positions
+ %
+ {%
+ \ifnum\pgf@matrix@numberofcolumns>0\relax%
+ \pgf@x=\csname pgf@matrix@minx1\endcsname\relax%
+ \pgf@x=-\pgf@x%
+ \expandafter\xdef\csname pgf@matrix@minx1\endcsname{\the\pgf@x}%
+ \fi
+ \c@pgf@counta=1\relax%
+ \loop%
+ \ifnum\c@pgf@counta<\pgf@matrix@numberofcolumns\relax%
+ \pgf@x=\csname pgf@matrix@minx\the\c@pgf@counta\endcsname\relax%
+ \advance\pgf@x by\csname pgf@matrix@maxx\the\c@pgf@counta\endcsname\relax%
+ \advance\c@pgf@counta by1\relax%
+ \pgf@xa=\csname pgf@matrix@minx\the\c@pgf@counta\endcsname\relax%
+ \advance\pgf@x by-\pgf@xa\relax%
+ \expandafter\xdef\csname pgf@matrix@minx\the\c@pgf@counta\endcsname{\the\pgf@x}%
+ \repeat%
+ }%
+}%
+
+
+% Shift the nodes to their origins
+
+% The following procedure shifts all nodes in
+% \pgf@matrix@node@list to their location inside a temporary
+% picture. This picture will later be shifted again to its final
+% position in the real picture.
+
+\def\pgf@matrix@shift@nodes@initial{%
+ {%
+ \pgfutil@for\pgf@matrix@node@name:=\pgf@matrix@node@list\do{%
+ \ifx\pgf@matrix@node@name\pgfutil@empty%
+ \else%
+ \expandafter\ifx\csname pgf@matrix@node@visited@\pgf@matrix@node@name\endcsname\relax%
+ \pgf@shift@node{\pgf@matrix@node@name}{%
+ \pgf@x=\csname pgf@matrix@minx%
+ \expandafter\expandafter\expandafter\pgfutil@secondoftwo\csname pgf@matrix@node@location@\pgf@matrix@node@name\endcsname\endcsname%
+ \pgf@y=\csname pgf@matrix@miny%
+ \expandafter\expandafter\expandafter\pgfutil@firstoftwo\csname pgf@matrix@node@location@\pgf@matrix@node@name\endcsname\endcsname%
+ }%
+ \expandafter\let\csname pgf@matrix@node@visited@\pgf@matrix@node@name\endcsname=\pgfutil@empty%
+ \fi%
+ \fi%
+ }%
+ }%
+}%
+
+
+% The second shifting, done in the following procedure, shifts all
+% nodes to their real positions inside the real picture.
+
+\def\pgf@matrix@shift@nodes@secondary#1{%
+ \pgfutil@for\pgf@matrix@node@name:=\pgf@matrix@node@list\do{%
+ \ifx\pgf@matrix@node@name\pgfutil@empty%
+ \else%
+ \expandafter\ifx\csname pgf@matrix@node@visited@\pgf@matrix@node@name\endcsname\relax%
+ \pgf@shift@node{\pgf@matrix@node@name}{#1}%
+ \expandafter\let\csname pgf@matrix@node@visited@\pgf@matrix@node@name\endcsname=\pgfutil@empty%
+ \fi%
+ \fi%
+ }%
+}%
+
+
+% End of line
+\def\pgfmatrixendrow{%
+ % if the cell contains nothing, the following \let will be at the
+ % beginning (macro expansion has stopped here since neither \omit
+ % nor \span was found)
+ \let\pgf@matrix@signal@cell@end=\pgf@matrix@signal@cell@end
+ \pgf@matrix@last@cell@in@rowtrue%
+ \xdef\pgf@matrix@rowsep{\pgfmatrixrowsep}%
+ &\pgf@matrix@correct@calltrue%
+ \global\pgf@matrix@fixedfalse%
+ \pgf@y=0pt%
+ \pgf@matrix@addtolength\pgf@y{\pgf@matrix@rowsep}%
+ \pgfutil@ifnextchar[{\pgfmatrixendrow@skip}{\pgf@matrix@finish@line}%
+}%
+\newif\ifpgf@matrix@last@cell@in@row
+
+\def\pgf@matrix@signal@cell@end{\pgf@matrix@signal@cell@end}%
+% exact definition does not matter, only needs to be unique.
+
+\def\pgfmatrixendrow@skip[#1]{%
+ \pgf@matrix@addtolength\pgf@y{#1}%
+ \pgf@matrix@finish@line%
+}%
+
+\def\pgf@matrix@finish@line{%
+ \global\pgf@y=\pgf@y%
+ \pgf@ya=-\pgf@y%
+ \global\advance\pgf@ya by\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname%
+ \expandafter\xdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{\the\pgf@ya}%
+ \pgfutil@ifnextchar\egroup{\cr\pgf@end@matrix}{\pgf@matrix@no@eom@found}%
+}%
+
+\def\pgf@matrix@eom@found{%
+ \cr%
+ \pgf@end@matrix%
+}%
+
+\def\pgf@matrix@no@eom@found{%
+ \cr%
+ \noalign{\vskip\pgf@y%
+ \ifpgf@matrix@fixed%
+ \vskip\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname% unskip
+ \vskip\pgf@y%
+ \pgf@y=-\pgf@y%
+ \expandafter\xdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{\the\pgf@y}%
+ \gdef\pgf@matrix@row@finish{\global\pgf@picmaxy=0pt}%
+ \else%
+ \global\let\pgf@matrix@row@finish=\pgfutil@empty%
+ \fi%
+ }%
+}%
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmodulenonlineartransformations.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmodulenonlineartransformations.code.tex
new file mode 100644
index 0000000000..55c9d6f651
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmodulenonlineartransformations.code.tex
@@ -0,0 +1,342 @@
+% 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{pgfmodulenonlineartransformations.code.tex}
+
+
+%
+% This file defines commands for nonlinear coordinate systems. This is
+% needed, for instance, for bend arrow heads.
+%
+%
+% Non-linear coordinate systems transform coordinates, in addition to
+% the normal linear transformations, in a, well, non-linear way. An
+% example are polar coordinates.
+%
+% Like the linear transformations, non-linear transformations are
+% applied on a low level and they are integrated into the whole path
+% construction mechanism. So, while \pgfpointpolar also "does
+% something nonlinear", it just provides a way of computing a
+% coordinate. In contrast, installing a polar transformation will
+% transform everything being drawn using the \pgfpath... commands an
+% will even turn a straight line into a circle.
+%
+% Since computing non-linear transformations is expensive, they are
+% only applied "if really necessary".
+
+
+
+
+% Return a transformed point
+%
+% #1 = a point
+%
+% Description:
+%
+% Applies the current transformation and the current nonlinear
+% transformation to the given point and returns the result in \pgf@x/y.
+
+\def\pgfpointtransformednonlinear#1{%
+ \pgf@process{%
+ #1%
+ \pgf@pos@transform@glob%
+ \pgf@nlt@list%
+ }
+}%
+
+
+
+
+% Approximate the nonlinear translation locally
+%
+% Description:
+%
+% Does a "local synchronization" of the nonlinear transformation with
+% the linear transformation regarding the translation part of the
+% current nonlinear transformation. The *linear* transformation will be
+% updated so that it translates things to the point to which the
+% nonlinear transformation transforms the origin. The nonlinear
+% transformation will be reset.
+%
+% The net effect is that you can now draw things near the origin as
+% before, but with just a linear transformation in force. Note that
+% the coordinate system will not be rotated, only a shift is done (use
+% the "real" local sync for a full sync).
+
+\def\pgfapproximatenonlineartranslation{%
+ \ifx\pgf@nlt@list\pgfutil@empty%
+ \else%
+ \pgfpointtransformednonlinear{\pgfpointorigin}%
+ \pgf@pt@x=\pgf@x%
+ \pgf@pt@y=\pgf@y%
+ \let\pgf@nlt@list\pgfutil@empty%
+ \let\pgf@nlt@moveto\pgf@lt@moveto%
+ \let\pgf@nlt@lineto\pgf@lt@lineto%
+ \let\pgf@nlt@curveto\pgf@lt@curveto%
+ \let\pgf@nlt@closepath\pgf@lt@closepath%
+ \fi%
+}%
+
+
+
+% Local sync translation
+%
+% Description:
+%
+% Does a "complete local synchronization" of the nonlinear
+% transformation with the linear transformation. The *linear*
+% transformation will be updated so that it transforms things to the
+% point to which the nonlinear transformation transforms the
+% origin. The nonlinear transformation will be reset.
+%
+% The net effect is that you can now draw things near the origin as
+% before, but with just a linear transformation in force.
+
+\def\pgfapproximatenonlineartransformation{%
+ \ifx\pgf@nlt@list\pgfutil@empty%
+ \else%
+ \pgfpointtransformednonlinear{\pgfpoint{1pt}{0pt}}%
+ \pgf@xa\pgf@x
+ \pgf@ya\pgf@y
+ \pgfpointtransformednonlinear{\pgfpoint{0pt}{1pt}}%
+ \pgf@xb\pgf@x
+ \pgf@yb\pgf@y
+ \pgfpointtransformednonlinear{\pgfpointorigin}%
+ \advance\pgf@xa by-\pgf@x
+ \advance\pgf@xb by-\pgf@x
+ \advance\pgf@ya by-\pgf@y
+ \advance\pgf@yb by-\pgf@y
+ \pgfsettransformentries{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@xb}{\pgf@sys@tonumber\pgf@yb}{\pgf@x}{\pgf@y}%
+ \let\pgf@nlt@list\pgfutil@empty%
+ \let\pgf@nlt@moveto\pgf@lt@moveto%
+ \let\pgf@nlt@lineto\pgf@lt@lineto%
+ \let\pgf@nlt@curveto\pgf@lt@curveto%
+ \let\pgf@nlt@closepath\pgf@lt@closepath%
+ \fi%
+}%
+
+
+
+% Adds a non-linear transformation to the current list of
+% transformations.
+%
+% #1 = code
+%
+% Description:
+%
+% When the code #1 is called, \pgf@x and \pgf@y will be set to some
+% values, let us call this the point p. The nonlinear transformation
+% will now map this point to a new point f(p). The coordinates of this
+% point should be returned in \pgf@x and \pgf@y. Furthermore, consider
+% the two "unit tangents" (going in $x$-direction and in
+% $y$-direction) at point p. The nonlinear transformation will map
+% these to new tangents, t_x and t_y. The (not necessarily normalized)
+% vectors t_x and t_y should be returned in pgf@xa and -ya and pgf@xb
+% and pgf@yb. The macro should not do any global assignments except to
+% \pgf@x and \pgf@y, but may do arbitrary local assignments.
+%
+% The effect of installing a new transformation is the following: As
+% long as there is at least one nonlinear transformation installed,
+% whenever the path construction commands add a curve or line to the
+% softpath, the line or curve will be "bend" by applying all of the
+% nonlinear transformation installed. In particular, straight lines
+% will be replaced by curves.
+%
+% Note that the normal linear transformation are always applied before
+% any nonlinear transformations are applied.
+
+\def\pgftransformnonlinear#1{%
+ \expandafter\def\expandafter\pgf@nlt@list\expandafter{\pgf@nlt@list#1}%
+ \let\pgf@nlt@moveto\pgf@nlt@moveto@nlt
+ \let\pgf@nlt@lineto\pgf@nlt@lineto@nlt
+ \let\pgf@nlt@curveto\pgf@nlt@curveto@nlt
+ \let\pgf@nlt@closepath\pgf@nlt@closepath@nlt
+}%
+
+\def\pgf@nlt@moveto@nlt#1#2{%
+ {%
+ \pgfutil@tempdima#1%
+ \pgfutil@tempdimb#2%
+ \pgf@x\pgfutil@tempdima%
+ \pgf@y\pgfutil@tempdimb%
+ \xdef\pgf@nlt@last@moveto@orig{{\the\pgf@x}{\the\pgf@y}}%
+ \pgf@nlt@list%
+ \xdef\pgf@nlt@last@moveto@trans{{\the\pgf@x}{\the\pgf@y}}%
+ \xdef\pgf@nlt@last@moveto@xaxis{{\the\pgf@xa}{\the\pgf@ya}}%
+ \xdef\pgf@nlt@last@moveto@yaxis{{\the\pgf@xb}{\the\pgf@yb}}%
+ \pgf@protocolsizes{\pgf@x}{\pgf@y}%
+ \pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}%
+ \global\let\pgf@nlt@last@coord@orig\pgf@nlt@last@moveto@orig%
+ \global\let\pgf@nlt@last@coord@trans\pgf@nlt@last@moveto@trans%
+ \global\let\pgf@nlt@last@coord@xaxis\pgf@nlt@last@moveto@xaxis%
+ \global\let\pgf@nlt@last@coord@yaxis\pgf@nlt@last@moveto@yaxis%
+ }%
+}%
+
+
+\def\pgf@nlt@lineto@nlt#1#2{%
+ {%
+ \edef\pgf@temp{\pgf@xc\the#1\pgf@yc\the#2}%
+ \pgf@temp%
+ \expandafter\pgfqpoint\pgf@nlt@last@coord@orig%
+ \expandafter\pgf@nlt@set@temps\pgf@nlt@last@coord@trans%
+ % Test, whether the points are quite near:
+ \pgf@xa\pgf@x\advance\pgf@xa by-\pgf@xc%
+ \pgf@ya\pgf@y\advance\pgf@ya by-\pgf@yc%
+ \pgfutil@tempswafalse%
+ \ifdim\pgf@xa<0.1pt\relax\ifdim\pgf@xa>-0.1pt\relax\ifdim\pgf@ya<0.1pt\relax\ifdim\pgf@ya>-0.1pt\relax\pgfutil@tempswatrue\fi\fi\fi\fi%
+ \ifpgfutil@tempswa%
+ \pgf@x\pgf@xc\pgf@y\pgf@yc%
+ \xdef\pgf@nlt@last@coord@orig{{\the\pgf@x}{\the\pgf@y}}%
+ \pgf@process{\pgf@nlt@list}%
+ \xdef\pgf@nlt@last@coord@trans{{\the\pgf@x}{\the\pgf@y}}%
+ \xdef\pgf@nlt@last@coord@xaxis{{\the\pgf@xa}{\the\pgf@ya}}%
+ \xdef\pgf@nlt@last@coord@yaxis{{\the\pgf@xb}{\the\pgf@yb}}%
+ \pgf@protocolsizes{\pgf@x}{\pgf@y}%
+ \pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}%
+ \else%
+ % Compute support points
+ \pgf@xb=.333333\pgf@x%
+ \advance\pgf@xb by.666666\pgf@xc%
+ \pgf@yb=.333333\pgf@y%
+ \advance\pgf@yb by.666666\pgf@yc%
+ \pgf@xa=.333333\pgf@xc%
+ \advance\pgf@xa by.666666\pgf@x%
+ \pgf@ya=.333333\pgf@yc%
+ \advance\pgf@ya by.666666\pgf@y%
+ \pgf@nlt@inner@curve%
+ \fi%
+ }%
+}%
+
+\def\pgf@nlt@set@temps#1#2{%
+ \pgfutil@tempdima#1\pgfutil@tempdimb#2%
+}%
+
+\def\pgf@nlt@curveto@nlt#1#2#3#4#5#6{%
+ {%
+ \edef\pgf@temp{\pgf@xa\the#1\pgf@ya\the#2\pgf@xb\the#3\pgf@yb\the#4\pgf@xc\the#5\pgf@yc\the#6}%
+ \pgf@temp%
+ \pgf@nlt@inner@curve%
+ }%
+}%
+
+\newdimen\pgftransformnonlinearflatness
+\pgftransformnonlinearflatness=5pt
+\def\pgfsettransformnonlinearflatness#1{\pgfmathsetlength\pgftransformnonlinearflatness{#1}}%
+
+
+
+% Compute a curve from \pgf@nlt@last@coord@orig to \pgf@xc/\pgf@yc via the
+% controls \pgf@xa/\pgf@ya and \pgf@xb/\pgf@yb.
+\def\pgf@nlt@inner@curve{%
+ \expandafter\pgfqpoint\pgf@nlt@last@coord@orig%
+ % Save delta of supports:
+ \pgfutil@tempdima\pgf@xa\advance\pgfutil@tempdima by-\pgf@xb
+ \pgfutil@tempdimb\pgf@ya\advance\pgfutil@tempdimb by-\pgf@yb
+ \begingroup
+ % Replace supports by relative supports
+ \advance\pgf@xa by-\pgf@x%
+ \advance\pgf@ya by-\pgf@y%
+ \advance\pgf@xb by-\pgf@xc%
+ \advance\pgf@yb by-\pgf@yc%
+ %
+ % Now, test whether the flatness is satisfied:
+ %
+ \pgfutil@tempswafalse
+ \ifdim\pgfutil@tempdima>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgfutil@tempdima<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgfutil@tempdimb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgfutil@tempdimb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@xa>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@xa<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@ya>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@ya<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@xb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@xb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@yb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifdim\pgf@yb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi%
+ \ifpgfutil@tempswa%
+ \endgroup% Undo the adjustments...
+ {%
+ \edef\pgf@orig@xya{\pgf@xa\the\pgf@xa\pgf@ya\the\pgf@ya}
+ \edef\pgf@orig@xyb{\pgf@xb\the\pgf@xb\pgf@yb\the\pgf@yb}
+ \edef\pgf@orig@xyc{\pgf@xc\the\pgf@xc\pgf@yc\the\pgf@yc}
+ \pgfpointcurveattime{.5}%
+ {\expandafter\pgfqpoint\pgf@nlt@last@coord@orig}%
+ {\pgf@x\pgf@xa\pgf@y\pgf@ya}%
+ {\pgf@x\pgf@xb\pgf@y\pgf@yb}%
+ {\pgf@x\pgf@xc\pgf@y\pgf@yc}%
+ % First new curve:
+ % Start is at last@coord@orig,
+ % first support is at last@coord@orig*t + s*(original xa/ya)
+ % second support is at xb/yb
+ % target is at x/y
+ {%
+ % Target:
+ \pgf@xc\pgf@x\pgf@yc\pgf@y
+ % First support:
+ \expandafter\pgfqpoint\pgf@nlt@last@coord@orig%
+ \pgf@orig@xya%
+ \pgf@xa\pgf@time@s\pgf@xa\advance\pgf@xa by\pgf@time@t\pgf@x%
+ \pgf@ya\pgf@time@s\pgf@ya\advance\pgf@ya by\pgf@time@t\pgf@y%
+ \pgf@nlt@inner@curve%
+ }%
+ % Second new curve:
+ % Start is at (new) last@coord@orig
+ % first support is at xa/ya
+ % second support is at t*(original xb/yb) + s*(original xc/yc)
+ % target is at original xc/yc
+ {%
+ \pgf@orig@xyb%
+ \pgf@orig@xyc%
+ \pgf@xb\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc%
+ \pgf@yb\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc%
+ \pgf@nlt@inner@curve%
+ }%
+ }%
+ \else%
+ \endgroup% Snap back...
+ \pgf@nlt@do@inner@curve%
+ \fi%
+}%
+
+\def\pgf@nlt@do@inner@curve{%
+ \pgf@process{\pgf@x\pgf@xa\pgf@y\pgf@ya\pgf@nlt@list}%
+ \pgf@xa\pgf@x\pgf@ya\pgf@y%
+ \pgf@process{\pgf@x\pgf@xb\pgf@y\pgf@yb\pgf@nlt@list}%
+ \pgf@xb\pgf@x\pgf@yb\pgf@y%
+ \xdef\pgf@nlt@last@coord@orig{{\the\pgf@xc}{\the\pgf@yc}}%
+ \pgf@process{\pgf@x\pgf@xc\pgf@y\pgf@yc\pgf@nlt@list}%
+ \pgf@xc\pgf@x\pgf@yc\pgf@y%
+ \xdef\pgf@nlt@last@coord@trans{{\the\pgf@xc}{\the\pgf@yc}}%
+ \pgf@protocolsizes{\pgf@xa}{\pgf@ya}%
+ \pgf@protocolsizes{\pgf@xb}{\pgf@yb}%
+ \pgf@protocolsizes{\pgf@xc}{\pgf@yc}%
+ \pgfsyssoftpath@curveto{\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}{\the\pgf@xc}{\the\pgf@yc}%
+}%
+
+
+\def\pgf@nlt@closepath@nlt{%
+ {%
+ \expandafter\pgfqpoint\pgf@nlt@last@moveto@orig%
+ \expandafter\pgf@nlt@set@temps\pgf@nlt@last@coord@orig%
+ \advance\pgfutil@tempdima by-\pgf@x%
+ \advance\pgfutil@tempdimb by-\pgf@y%
+ \pgfutil@tempswatrue%
+ \ifdim\pgfutil@tempdima<0.01pt\relax\ifdim\pgfutil@tempdima>-0.01pt\relax\ifdim\pgfutil@tempdimb<0.01pt\relax\ifdim\pgfutil@tempdimb>-0.01pt\relax\pgfutil@tempswafalse\fi\fi\fi\fi%
+ \ifpgfutil@tempswa%
+ \pgf@nlt@lineto@nlt{\pgf@x}{\pgf@y}%
+ \fi%
+ \pgfsyssoftpath@closepath%
+ }%
+}%
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduleoo.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduleoo.code.tex
new file mode 100644
index 0000000000..86c1e8e996
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduleoo.code.tex
@@ -0,0 +1,844 @@
+% Copyright 2019 by Till Tantau
+% Copyright 2019 by Saso Zivanovic
+%
+% 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.
+%
+% Based on pgfmoduleoo.code.tex v1.8 by Till Tantau. This version adds inheritance.
+
+
+
+% Support of object-oriented programming in TeX, with inheritance.
+
+
+% The oo support works as follows:
+%
+% The main supported concepts are classes, objects, methods,
+% attributes and signal/slots. A class defines a set of methods, which are,
+% in the end, just normal TeX macros. Once a class has been created,
+% it can be instantiated by calling the \pgfoonew command, resulting
+% in a new object. Objects are local to their group. Given an object,
+% you can send it a message, resulting in the method code of the
+% object's method to be executed. While an object exists, it has a set
+% of attributes whose values can change over time. Attributes values
+% are not local to TeX groups, rather their life-cycle is the same as
+% the object's (which, however, is local to the group in which the
+% object was declared).
+%
+% The implementation is as follows: There is an ID counter that is
+% increased each time an object is created. This counter is local to
+% the group, which means that when a group ends the counter will
+% revert to the previous value, allowing objects to the reused in
+% subsequent groups.
+%
+% A method is just a normal \TeX macro, but to call it you write
+% \objecthandle.methodname(parameters). The \objecthandle is a macro
+% that is created when you say \pgfoonew. The special object
+% \pgfoothis is the current object.
+%
+% Attributes are stored globally in internal TeX macros whose name is
+% composed of the object number and the attribute name.
+
+
+
+
+% Declares a class
+%
+% #1 = class name
+% #2 = methods
+%
+% Description:
+%
+% This command declares a class for future use. Inside #2, the macro
+% \method can be used to declare a method. The \method macro takes a
+% method name, parameters (methods are normal TeX macros, after all)
+% and body.
+
+% base classes are put in parenthesis before the new class name, but
+% are optional.
+\def\pgfooclass{%
+ \pgfutil@ifnextchar ({%
+ \pgfooclass@
+ }{%
+ \pgfooclass@()
+ }%
+}%
+\long\def\pgfooclass@(#1)#2#3{%
+ \def\pgfoo@classname{#2}%
+ \expandafter\ifx\csname pgfooY\pgfoo@classname.@pgfooinit\endcsname\relax\else
+ \pgferror{class #2 is already defined}%
+ \fi
+ \pgfoo@ciii{#2}{#1}%
+ \expandafter\let\csname pgfooY#2@pgfoo@mro\endcsname\pgfoo@mro
+ \let\pgfoo@origmethod=\method%
+ \let\pgfoo@origattribute=\attribute%
+ \let\method=\pgfoo@declaremethod%
+ \let\attribute=\pgfoo@declareattribute%
+ \let\pgfoo@attributes=\pgfutil@empty%
+ \let\pgfoo@methods=\pgfutil@empty%
+ #3%
+ % inherit
+ \def\pgfoo@temp@baseclasses{#1}%
+ \pgfoo@inherit@methods
+ \pgfoo@inherit@attributes
+ % Always present (and never inherited) methods:
+ \expandafter\let\csname pgfooY\pgfoo@classname.get handle\endcsname\pgfoo@obj%
+ \expandafter\let\csname pgfooY\pgfoo@classname.get id\endcsname\pgfoo@id%
+ % for compatibility with previous versions of pgfoo, define method
+ % with the same name as the class as a synonym for init
+ \expandafter\let\expandafter\pgfoo@init\csname pgfooY\pgfoo@classname.init\endcsname
+ \expandafter\let\csname pgfooY\pgfoo@classname.\pgfoo@classname\endcsname\pgfoo@init
+ % Cleanup
+ \let\method=\pgfoo@origmethod%
+ \let\attribute=\pgfoo@origattribute%
+}%
+
+\def\pgfoo@emptyinit(){}%
+\def\pgfoo@escapeif#1#2\fi{\fi#1}% a little helper
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Compute MRO using C3 algorithm
+% The sequences are enclosed in brackets; elements of sequences and
+% the big list are terminated by a comma and a dot, respectively. (Why
+% comma *and* a dot: TeX's parset---brackets don't form groups! Soooo,
+% why not braces? Because I don't know how do delete excess "{},"s...)
+
+% #1 = current class, #2 = list of base classes
+\def\pgfoo@ciii#1#2{%
+ % \pgfoo@seq will hold a list of sequences.
+ % (i) the first sequence has just one element: the current class
+ \def\pgfoo@seq{[#1,].}%
+ % (ii) every subclass has a sequence (in the order as they were
+ % given): the class' sequence is its mro.
+ \pgfutil@for\pgfoo@baseclass:={#2}\do{%
+ \edef\pgfoo@baseclass@mro{\csname pgfooY\pgfoo@baseclass @pgfoo@mro\endcsname}%
+ \expandafter\ifx\expandafter\relax\pgfoo@baseclass@mro\relax\else
+ \edef\pgfoo@seq{\pgfoo@seq[\pgfoo@baseclass@mro,].}%
+ \fi
+ }%
+ % The final sequence is a sequence of base classes, in the order as
+ % they were given.
+ \ifx\relax#2\relax\else
+ \edef\pgfoo@seq{\pgfoo@seq[#2,].}%
+ \fi
+ \edef\pgfoo@temp{()(\pgfoo@seq)}%
+ \expandafter\pgfoo@ciii@merge\pgfoo@temp
+}%
+
+% #1 = MRO so far
+% #2 = remaining sequences
+% no empty sequences [] should arrive here: they should be removed
+% before calling this macro
+\def\pgfoo@ciii@merge(#1)(#2){%
+ \ifx\relax#2\relax
+ \pgfoo@ciii@done(#1)%
+ \else\pgfoo@escapeif{% split #2
+ \pgfoo@ciii@merge@A(#1)(#2)%
+ }\fi%
+}%
+% a splitter: to be only called from \pgfoo@ciii@merge
+\def\pgfoo@ciii@merge@A(#1)(#2.#3){%
+ \ifx\relax#3\relax % if #3 is empty, we can take the shortcut
+ \pgfoo@ciii@mergeA@done(#1)(#2)%
+ \else\pgfoo@escapeif{%
+ \pgfoo@ciii@merge@checkHead(#1)()(#2)()(#3)%
+ }\fi
+}%
+
+\def\pgfoo@ciii@mergeA@done(#1)([#2]){%
+ \pgfoo@ciii@done(#1#2)%
+}%
+
+% #1 = MRO so far
+% #2 = sequences with bad heads (dot after each sequence)
+% [#3,#4] = the sequence whose head we're testing right
+% now---obviously, it should not be empty! (#3 has no comma,
+% #4 has a comma after each class name)
+% #5 = #3 does not occur in the tail of these sequences (dot after
+% each sequence)
+% #6 = the remaining sequences (dot after each sequence)
+\def\pgfoo@ciii@merge@checkHead(#1)(#2)([#3,#4])(#5)(#6){%
+ \pgfutil@in@{[#3,}{#2}%
+ \ifpgfutil@in@\pgfoo@escapeif{% #3 is already blacklisted
+ \pgfoo@ciii@clean\pgfoo@ciii@merge@checkHead@P{(#1)(#2[#3,#4].)(#5#6)}%
+ }\else\pgfoo@escapeif{%
+ \ifx\relax#6\relax\pgfoo@escapeif{% no more sequences to test the head against!
+ % so, #3 is a good head, and we can recurse
+ \pgfoo@ciii@goodHeadFound(#1)(#3)(#2[#4].#5)%
+ }\else\pgfoo@escapeif{% split #6 and get to work
+ \pgfoo@ciii@merge@checkHead@A(#1)(#2)([#3,#4])(#5)(#6)%
+ }\fi
+ }\fi
+}%
+% splitter: to be only called from \pgfoo@ciii@merge@checkHead
+% we will check if #3 occurs in the tail of #6
+\def\pgfoo@ciii@merge@checkHead@A(#1)(#2)([#3,#4])(#5)(#6.#7){%
+ \pgfoo@ciii@merge@checkHead@B(#1)(#2)([#3,#4])(#5)(#6)(#7)%
+}%
+% splitter: to be only called from \pgfoo@ciii@merge@checkHead@A
+% &worker: we will check if #3 occurs in #7. If it does, #3 is a bad head.
+\def\pgfoo@ciii@merge@checkHead@B(#1)(#2)([#3,#4])(#5)([#6,#7])(#8){%
+% \def\pgfoo@ciii@tempA{#3}\def\pgfoo@ciii@tempB{#5}%
+% \ifx\pgfoo@ciii@tempA\pgfoo@ciii@tempB
+% \pgferror{An attempt to derive from the same class twice}%
+% \else\pgfoo@escapeif{%
+ \pgfutil@in@{,#3,}{,#7}%
+ \ifpgfutil@in@\pgfoo@escapeif{% bad head! get next head and restart
+ % but: need to clean up first!
+ \pgfoo@ciii@clean\pgfoo@ciii@merge@checkHead@P{(#1)(#2[#3,#4].)(#5[#6,#7].#8)}%
+ }\else\pgfoo@escapeif{% so far, so good
+ \ifx\relax#8\relax\pgfoo@escapeif{% if #8 is empty, we won:
+ % #3 is a good head! we will move it to MRO
+ % but clean-up first!
+ \pgfoo@ciii@goodHeadFound(#1)(#3)(#2[#4].#5[#6,#7].)%
+ }\else\pgfoo@escapeif{% proceed to the first seq in #8
+ \pgfoo@ciii@clean\pgfoo@ciii@merge@checkHead{(#1)(#2)([#3,#4])(#5[#6,#7].)(#8)}%
+ }\fi
+ }\fi
+% }\fi
+}%
+
+% #1 = MRO
+% #2 = good head
+% #3 = the remaining sequences (in need of removing the good head from
+% them, and then also some general cleanup)
+\def\pgfoo@ciii@goodHeadFound(#1)(#2)(#3){%
+ \pgfutil@in@{,#2,}{#3}%
+ \ifpgfutil@in@\pgfoo@escapeif{%
+ \def\pgfoo@ciii@removeGoodHead(##1)(##2)(##3,#2,##4){%
+ \pgfoo@ciii@goodHeadFound(##1)(##2)(##3,##4)}%
+ \pgfoo@ciii@removeGoodHead(#1)(#2)(#3)%
+ }\else\pgfoo@escapeif{%
+ \pgfutil@in@{[#2,}{#3}%
+ \ifpgfutil@in@\pgfoo@escapeif{%
+ \def\pgfoo@ciii@removeGoodHead(##1)(##2)(##3[#2,##4){%
+ \pgfoo@ciii@goodHeadFound(##1)(##2)(##3[##4)}%
+ \pgfoo@ciii@removeGoodHead(#1)(#2)(#3)%
+ }\else\pgfoo@escapeif{%
+ \pgfoo@ciii@clean\pgfoo@ciii@merge{(#1#2,)(#3)}%
+ }\fi
+ }\fi
+}%
+
+% mediates between the bad head exit of \pgfoo@ciii@merge@checkHead@B
+% and \pgfoo@ciii@merge@checkHead; we need the mediator because #3
+% below might have been affected by cleaning.
+\def\pgfoo@ciii@merge@checkHead@P(#1)(#2)(#3){%
+ \if\relax#3\relax % no more good head candidates!
+ \pgferror{Bad MRO: There is no good (monotonic etc.)
+ Method Resolution Order for your class hierarchy}%
+ \else\pgfoo@escapeif{%
+ \pgfoo@ciii@merge@checkHead@Q(#1)(#2)(#3)%
+ }\fi
+}%
+% splitter for \pgfoo@ciii@merge@checkHead@P
+% #3 = the sequence containing the newest good head candidate
+\def\pgfoo@ciii@merge@checkHead@Q(#1)(#2)(#3.#4){%
+ \pgfoo@ciii@merge@checkHead(#1)(#2)(#3)()(#4)%
+}%
+
+% cyclically removes all occurrences of "[]," and "[]." (i.e., empty
+% sequences) in #2. When done, calls #1 with whatever remains.
+\def\pgfoo@ciii@clean#1#2{% clean commas
+ \pgfutil@in@{[].}{#2}% clean dots
+ \ifpgfutil@in@\pgfoo@escapeif{%
+ \pgfoo@ciii@clean@dot#1#2\pgfoo@ciii@clean@END
+ }\else\pgfoo@escapeif{%
+ #1#2%
+ }\fi
+}%
+\def\pgfoo@ciii@clean@dot#1#2[].#3\pgfoo@ciii@clean@END{%
+ \pgfoo@ciii@clean#1{#2#3}%
+}%
+
+\def\pgfoo@ciii@done(#1,){%
+ \def\pgfoo@mro{#1}%
+}%
+
+% end of C3
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% Declare a method
+%
+% Description:
+%
+% Defines a method. To use/invoke this method for an object \object,
+% you write \object.methodname(parameters). This will cause the method
+% body to be invoked with the argument "(parameters)".
+%
+% To define the method \method should be directly followed by the
+% method name and, then, by (, followed by a parameter pattern,
+% followed by ), followed by the message body. Spaces are allowed only
+% after "\method" and after the closing ).
+%
+% Example:
+%
+% \pgfooclass{MyPlot}{
+%
+% \attribute x=0;
+% \attribute y=0;
+%
+% \method MyPlot() {
+% }
+%
+% \method getX(#1) {
+% \pgfooget{x}{#1}
+% }
+%
+% \method setPoint(#1,#2) {
+% \pgfooset{x}{#1}
+% \pgfooset{y}{#2}
+% }
+% }
+
+% define the method macro and append the method to the method collection
+\long\def\pgfoo@declaremethod#1(#2)#3{%
+ \def\pgfoo@method{#1}%
+ \ifx\pgfoo@classname\pgfoo@method
+ \def\pgfoo@method{init}%
+ \fi
+ \expandafter\long\expandafter\def\csname pgfooY\pgfoo@classname.\pgfoo@method\endcsname(#2){#3}%
+ \edef\pgfoo@methods{\pgfoo@methods,\pgfoo@method}%
+}%
+
+\def\pgfoo@inherit@methods{%
+ % for non-derived classes:
+ \expandafter\ifx\expandafter\relax\pgfoo@temp@baseclasses\relax
+ % if init is not defined, define an empty one
+ \expandafter\ifx\csname pgfooY\pgfoo@classname.init\endcsname\relax
+ \expandafter\let\csname pgfooY\pgfoo@classname.init\endcsname\pgfoo@emptyinit%
+ \edef\pgfoo@methods{,init\pgfoo@methods}%
+ \fi
+ \fi
+ \if\relax\pgfoo@methods\relax\else
+ % gobble the initial comma
+ \edef\pgfoo@methods{\expandafter\pgfutil@gobble\pgfoo@methods}%
+ \fi
+ % remember the list of collected methods
+ \expandafter\let\csname pgfooY\pgfoo@classname @pgfoo@methods\endcsname\pgfoo@methods
+ % get MRO
+ \expandafter\let\expandafter\pgfoo@mro\csname pgfooY\pgfoo@classname @pgfoo@mro\endcsname
+ % loop throough base classes in MRO
+ \pgfutil@for\pgfoo@baseclass:=\pgfoo@mro\do{%
+ \ifx\pgfoo@baseclass\pgfoo@classname % skip self
+ \else\pgfoo@escapeif{%
+ % get methods defined in this base class
+ \expandafter\let\expandafter\pgfoo@methods\csname pgfooY\pgfoo@baseclass @pgfoo@methods\endcsname
+ \pgfutil@for\pgfoo@method:=\pgfoo@methods\do{% for each method
+ % check if it is already defined in our class
+ \expandafter\ifx\csname pgfooY\pgfoo@classname.\pgfoo@method\endcsname\relax
+ % if not, link the method name from our class to base class
+ \edef\pgfoo@temp{\noexpand\let
+ \expandafter\noexpand\csname pgfooY\pgfoo@classname.\pgfoo@method\endcsname
+ \expandafter\noexpand\csname pgfooY\pgfoo@baseclass.\pgfoo@method\endcsname}%
+ \pgfoo@temp
+ \fi
+ }%
+ }\fi
+ }%
+}%
+
+\def\pgfoosuper(#1,#2).#3({%
+ #2.get id(\pgfoo@temp@id)%
+ \edef\pgfoo@classname{\csname pgfooX\pgfoo@temp@id @class\endcsname}%
+ \def\pgfoo@super@A##1,#1,##2.##3({%
+ \pgfoo@super@B##2.##3(%
+ }%
+ \expandafter\let\expandafter\pgfoo@mro\csname pgfooY\pgfoo@classname @pgfoo@mro\endcsname
+ \expandafter\pgfoo@super@A\expandafter,\pgfoo@mro,.#3(%
+}%
+\def\pgfoo@super@B#1,#2.#3({%
+ \expandafter\ifx\csname pgfooY#1.#3\endcsname\relax
+ \pgfoo@escapeif{\pgfoo@super@B#2.#3(}%
+ \else
+ \pgfoo@escapeif{\expandafter\pgfoo@caller\pgfoo@temp@id.#1.#3(}%
+ \fi
+}%
+
+
+
+% Declare an attribute
+%
+% #1 = attribute name
+% #2 = optional default value
+%
+% Description:
+%
+% Declares the attribute #1 for the current class. If the attribute
+% name is followed by =, the text following the equal sign is the
+% default value.
+
+\def\pgfoo@declareattribute#1;{%
+ \pgfutil@in@{ =}{#1}%
+ \ifpgfutil@in@%
+ \pgfoo@declareunpackspace#1;%
+ \else%
+ \pgfutil@in@={#1}%
+ \ifpgfutil@in@%
+ \pgfoo@declareunpack#1;%
+ \else%
+ \pgfoo@declareattribute@\let{#1}\pgfutil@empty
+ \fi%
+ \fi%
+}%
+\def\pgfoo@declareunpack#1=#2;{\pgfoo@declareattribute@\def{#1}{{#2}}}%
+\def\pgfoo@declareunpackspace#1 =#2;{\pgfoo@declareattribute@\def{#1}{{#2}}}%
+
+% put the initial value in the class's namespace
+% put the attr name in a list
+\def\pgfoo@declareattribute@#1#2#3{%
+ \expandafter#1\csname pgfooY\pgfoo@classname @#2\endcsname#3%
+ \expandafter\def\expandafter\pgfoo@attributes\expandafter{\pgfoo@attributes,#2}%
+}%
+
+% for each base class:
+% for each attribute declared in that class:
+% add the attr on a list if it's not there yet
+% convert the list of (attr,class which it comes from) into an
+% efficient sequence of triples \op{attrname}\pointer-to-initial-value
+% (\op is then set differently in init and garbage collection)
+\def\pgfoo@inherit@attributes{%
+ % store the list of attributes declared in this class for use in
+ % derived classes
+ \if\relax\pgfoo@attributes\relax\else
+ \edef\pgfoo@attributes{\expandafter\pgfutil@gobble\pgfoo@attributes}% gobble comma
+ \fi
+ \expandafter\let\csname pgfooY\pgfoo@classname.@pgfoo@attributes\endcsname\pgfoo@attributes%
+ % get MRO
+ \expandafter\let\expandafter\pgfoo@mro\csname pgfooY\pgfoo@classname @pgfoo@mro\endcsname
+ \def\pgfoo@allattributes{}% here we will store the attrs declared in base classes
+ \pgfutil@for\pgfoo@baseclass:=\pgfoo@mro\do{% for each base class in MRO order
+ % the attributes declared in this base class
+ \expandafter\let\expandafter\pgfoo@attributes\csname pgfooY\pgfoo@baseclass.@pgfoo@attributes\endcsname
+ \pgfutil@for\pgfoo@attribute:=\pgfoo@attributes\do{% for each attribute
+ % check if we have already found it in some previous base class
+ \edef\pgfoo@temp{{,\pgfoo@attribute=}{\pgfoo@allattributes,}}%
+ \expandafter\pgfutil@in@\pgfoo@temp
+ \ifpgfutil@in@\else % don't overwrite
+ % append to the list
+ \edef\pgfoo@allattributes{\pgfoo@allattributes,\pgfoo@attribute=\pgfoo@baseclass}%
+ \fi
+ }%
+ }%
+ \if\relax\pgfoo@allattributes\relax\else
+ \edef\pgfoo@allattributes{\expandafter\pgfutil@gobble\pgfoo@allattributes}% gobble comma
+ \fi
+ % this macro will hold a list of attributes from all base classes
+ % we run this macro at init and gc
+ \def\pgfoo@process@attributes{}%
+ \pgfutil@for\pgfoo@attributeclass:=\pgfoo@allattributes\do{% for each (attribute, class) pair
+ % append to the attribute processor
+ \expandafter\pgfoo@inherit@attributes@appendattribute\pgfoo@attributeclass.%
+ }%
+ \expandafter\let\csname pgfooY\pgfoo@classname .@pgfoo@process@attributes\endcsname\pgfoo@process@attributes
+}%
+
+
+% #1=attr, #2=class which the attr comes from
+\def\pgfoo@inherit@attributes@appendattribute#1=#2.{%
+ \def\pgfoo@tempA{\pgfoo@attribute@op{#1}}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfoo@tempB\expandafter\expandafter\expandafter{\expandafter\pgfoo@tempA\csname pgfooY#2@#1\endcsname}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfoo@process@attributes\expandafter\expandafter\expandafter{\expandafter\pgfoo@process@attributes\pgfoo@tempB}%
+ % above is just this:
+ % \def\pgfoo@process@attributes{\pgfoo@process@attributes\pgfoo@attribute@op{#1}%
+ % \csname pgfooY#2@#1\endcsname}
+ % with \pgfoo@process@attributes and \csname expanded exactly once:
+}%
+
+% \pgfoo@attribute@op for garbage collection
+\def\pgfoo@gc@attribute#1#2{\pgfoolet{#1}\relax}%
+
+
+\newcount\pgfoo@objectcount
+\newcount\pgfoothis@count
+
+% The attribute value method
+%
+% #1 = attr
+%
+% This method inserts the current value of the given attribute for the
+% current object.
+
+\def\pgfoovalueof#1{%
+ \csname pgfooX\the\pgfoothis@count @#1\endcsname%
+}%
+
+
+% The attribute get method
+%
+% #1 = attr
+% #2 = macro
+%
+% This method makes the macro equal to the current value of the
+% attribute for the current object.
+
+\def\pgfooget#1#2{%
+ \expandafter\let\expandafter#2\csname pgfooX\the\pgfoothis@count @#1\endcsname%
+}%
+
+
+% The attribute set method
+%
+% #1 = attr
+% #2 = value
+%
+% This method sets the given attribute for the current object to the
+% given value.
+
+\long\def\pgfooset#1#2{%
+ \expandafter\gdef\csname pgfooX\the\pgfoothis@count @#1\endcsname{#2}%
+}%
+
+
+% The attribute set method (expanded version)
+%
+% #1 = attr
+% #2 = value
+%
+% This method sets the given attribute for the current object to the
+% expanded version of the given value.
+
+\long\def\pgfooeset#1#2{%
+ \expandafter\xdef\csname pgfooX\the\pgfoothis@count @#1\endcsname{#2}%
+}%
+
+
+% The attribute let method
+%
+% #1 = attr
+% #2 = value
+%
+% This method sets the given attribute for the current object to the
+% given value using \let.
+
+\def\pgfoolet#1#2{%
+ \expandafter\global\expandafter\let\csname pgfooX\the\pgfoothis@count @#1\endcsname#2%
+}%
+
+
+% Add something to an attribute at the end
+%
+% #1 = attr
+% #2 = code
+%
+% This method adds the give code to the attr at the end.
+
+\def\pgfooappend#1#2{%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgf@oo@temp\expandafter\expandafter\expandafter{\csname pgfooX\the\pgfoothis@count @#1\endcsname#2}%
+ \expandafter\global\expandafter\let\csname pgfooX\the\pgfoothis@count @#1\endcsname\pgf@oo@temp%
+}%
+
+
+% Add something to an attribute at the beginning
+%
+% #1 = attr
+% #2 = code
+%
+% This method adds the give code to the attr at the beginning.
+
+\def\pgfooprefix#1#2{%
+ \pgfooget{#1}\pgf@oo@temp%
+ \def\pgf@oo@@temp{#2}%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter\pgf@oo@temp%
+ \expandafter\expandafter\expandafter{\expandafter\pgf@oo@@temp\pgf@oo@temp}%
+ \pgfoolet{#1}\pgf@oo@temp%
+}%
+
+
+
+% Help macro for scanning arguments
+\newtoks\pgfoo@toks
+
+\def\pgfoo@collect@args{%
+ \pgfutil@ifnextchar\bgroup\pgfoo@collect@args@group\pgfoo@collect@args@nogroup%
+}%
+\def\pgfoo@collect@args@nogroup#1){%
+ \pgfoo@toks{#1}%
+ \pgfoo@continue%
+}%
+\def\pgfoo@collect@args@group#1{%
+ \pgfutil@ifnextchar){\pgfoo@toks{{#1}}\expandafter\pgfoo@continue\pgfutil@gobble}{\pgfoo@collect@args@nogroup{#1}}%
+}%
+
+
+% Instantiate an object
+%
+% Possible syntax:
+%
+% 1) \pgfoonew new <class name>(<constructor parameters)
+% 2) \pgfoonew \<objectname>=new <class name>(<constructor parameters)
+% 3) \pgfoonew{attribute}=new <class name>(<constructor parameters)
+%
+% Description:
+%
+% Creates an object. After the object has been created, the method
+% called <class name> (the constructor) is invoked. If the
+% \<objectname>= part is present, the macro is assigned to the newly
+% created object.
+
+\def\pgfoonew{%
+ \pgfutil@ifnextchar n{%
+ \pgfoo@new\pgfoo@dummy=%
+ }{%
+ \pgfutil@ifnextchar\bgroup{%
+ \pgfoo@new@attribute%
+ }{%
+ \pgfoo@new%
+ }%
+ }%
+}%
+\def\pgfoo@new#1={%
+ \def\pgfutil@reserved@a{#1}%
+ \let\pgfutil@next\pgfoo@@new
+ \futurelet\pgfutil@let@token\pgfutil@ignorespaces}%
+\def\pgfoo@@new new #1({%
+ \expandafter\ifx\csname pgfooY#1.get id\endcsname\relax%
+ \pgferror{Unknown class '#1'}%
+ \else%
+ \expandafter\pgfoo@new@create\pgfutil@reserved@a{#1}%
+ {%
+ \pgfoothis@count\pgfoo@objectcount%
+ \let\pgfoo@attribute@op\pgfoolet
+ \csname pgfooY#1.@pgfoo@process@attributes\endcsname%
+ }%
+ \let\pgfoo@continue=\pgf@oo@new@cont%
+ \expandafter\pgfoo@collect@args%
+ \fi%
+}%
+
+\def\pgf@oo@new@cont{%
+ \expandafter\pgfoolastobj\expandafter.\expandafter i\expandafter n\expandafter i\expandafter t\expandafter(\the\pgfoo@toks)%
+ \aftergroup\pgfoogc% cleanup after group
+}%
+
+\def\pgfoo@new@attribute#1={%
+ \def\pgfutil@reserved@a{#1}%
+ \let\pgfutil@next\pgfoo@@new@attribute
+ \futurelet\pgfutil@let@token\pgfutil@ignorespaces}%
+\def\pgfoo@@new@attribute new #1({%
+ \expandafter\ifx\csname pgfooY#1.get id\endcsname\relax%
+ \pgferror{Unknown class '#1'}%
+ \else%
+ \pgfoo@new@create\pgfoo@temp{#1}%
+ {%
+ \pgfoothis@count\pgfoo@objectcount%
+ \let\pgfoo@attribute@op\pgfoolet%
+ \csname pgfooY#1.@pgfoo@process@attributes\endcsname%
+ }%
+ \expandafter\pgfoolet\expandafter{\pgfutil@reserved@a}\pgfoo@temp%
+ \let\pgfoo@continue=\pgf@oo@new@cont%
+ \expandafter\pgfoo@collect@args%
+ \fi%
+}%
+
+\def\pgfoo@new@create#1#2{%
+ \advance\pgfoo@objectcount by 1\relax%
+ \edef\pgfoolastobj{\noexpand\pgfoo@caller{\the\pgfoo@objectcount}}%
+ \expandafter\gdef\csname pgfooX\the\pgfoo@objectcount @class\endcsname{#2}%
+ \let#1\pgfoolastobj%
+}%
+
+\def\pgfoo@caller#1.#2({%
+ \expandafter\let\expandafter\pgfoo@caller@temp\csname pgfooY\csname pgfooX#1@class\endcsname.#2\endcsname%
+ \ifx\pgfoo@caller@temp\relax%
+ % assume that #2 is of form "superclass.method"
+ \expandafter\let\expandafter\pgfoo@caller@temp\csname pgfooY#2\endcsname%
+ \ifx\pgfoo@caller@temp\relax%
+ \pgferror{Object #1 has no method '#2'}%
+ \fi%
+ \fi%
+ \def\pgf@marshal{%
+ \pgfoothis@count=#1\relax%
+ }%
+ \let\pgfoo@continue\pgfoo@caller@cont%
+ \pgfoo@collect@args%
+}%
+\def\pgfoo@caller@cont{%
+ \edef\pgf@marshal{%
+ \pgf@marshal%
+ \noexpand\pgfoo@caller@temp(\the\pgfoo@toks)%
+ }%
+ \expandafter\pgf@marshal\expandafter\pgfoothis@count\the\pgfoothis@count\relax%
+}%
+\let\pgfoo@orig@caller=\pgfoo@caller
+
+% The special "this" object
+
+\def\pgfoothis.#1({%
+ \expandafter\let\expandafter\pgfoo@caller@temp\csname pgfooY\csname pgfooX\the\pgfoothis@count @class\endcsname.#1\endcsname%
+ \ifx\pgfoo@caller@temp\relax%
+ % assume that #1 is of form "superclass.method"
+ \expandafter\let\expandafter\pgfoo@caller@temp\csname pgfooY#1\endcsname%
+ \fi%
+ \let\pgfoo@continue\pgfoothis@cont%
+ \pgfoo@collect@args%
+}%
+\def\pgfoothis@cont{%
+ \expandafter\pgfoo@caller@temp\expandafter(\the\pgfoo@toks)%
+}%
+
+
+
+% Get the object id
+%
+% #1 = macro to store the id
+%
+% Description:
+%
+% This special method allows you to access the object id. You can then
+% use \pgfoocall to call a method using this id. This is mainly useful
+% when you wish to store the id for a longer time.
+
+\def\pgfoo@id(#1){%
+ \edef#1{\the\pgfoothis@count}%
+}%
+
+% Yields the object with the given id
+%
+% #1 = id
+%
+% Description:
+%
+% Given an object id, \pgfooobj{<id>} will yield the object having
+% this id.
+
+\def\pgfooobj#1{%
+ \pgfoo@caller{#1}%
+}%
+
+
+% Get the object
+%
+% #1 = macro to store the object
+%
+% Description:
+%
+% This special method allows you to get a new handle to a given
+% object. If \obj is an object, you could normally just say
+% \let#1=\obj. However, if \obj happens to be \pgfoothis, then you may
+% wish to get a handle to the object itself, not to the special macro
+% \pgfoothis. In this case you can say \obj.get handle(#1).
+
+\def\pgfoo@obj(#1){%
+ \edef#1{\noexpand\pgfoo@caller{\the\pgfoothis@count}}%
+}%
+
+
+
+% The garbage collector
+%
+% Description:
+%
+% This method frees space occupied by unused objects. Garbage are
+% objects that have been destroyed because of the end of the scope in
+% which they were created. In this case, however, the memory used by
+% this object is not immediately reused because the attributes of the
+% object are actually stored in global variables. When the garbage
+% collector is called, it will set all these global variables to
+% \relax, thereby ensuring that no memory is needed for them.
+
+\def\pgfoogc{%
+ {%
+ % We do this in a group...
+ \pgfoothis@count\pgfoo@objectcount% this is temporary...
+ \let\pgfoo@next=\pgfoo@dogc%
+ \pgfoo@next%
+ }%
+}%
+\def\pgfoo@dogc{%
+ \advance\pgfoothis@count by 1\relax%
+ \expandafter\ifx\csname pgfooX\the\pgfoothis@count @class\endcsname\relax%
+ \let\pgfoo@next=\relax%
+ \else%
+ % Cleanup this object:
+ % The following is the fast version of \pgfooobj{\the\pgfoo@objectcount}.@pgfoogc:
+ \let\pgfoo@attribute@op\pgfoo@gc@attribute
+ \csname pgfooY\csname pgfooX\the\pgfoothis@count @class\endcsname.@pgfoo@process@attributes\endcsname%
+ \expandafter\global\expandafter\let\csname pgfooX\the\pgfoothis@count @class\endcsname\relax%
+ \fi%
+ \pgfoo@next%
+}%
+
+
+
+%
+%
+% Object class
+% defines method "copy"
+%
+%
+
+\pgfooclass{object}{%
+ \method copy(#1) {%
+ % create a new object
+ \edef\pgfoo@temp@classname{\csname pgfooX\the\pgfoothis@count @class\endcsname}%
+ \expandafter\pgfoo@new@create\expandafter#1\expandafter{\pgfoo@temp@classname}%
+ \def\pgfoo@copy@attributes##1##2{%
+ \pgfooget{##1}\pgfoo@attrvalue
+ \expandafter\let\csname pgfooX\the\pgfoo@objectcount @##1\endcsname\pgfoo@attrvalue
+ }%
+ \let\pgfoo@attribute@op\pgfoo@copy@attributes
+ \csname pgfooY\pgfoo@temp@classname .@pgfoo@process@attributes\endcsname
+ \aftergroup\pgfoogc% cleanup after group
+ }%
+}%
+
+
+%
+%
+% Signal class
+%
+%
+
+\pgfooclass{signal}
+{%
+ %
+ % This class implements signals.
+ %
+ % After you have created a signal object, you can call
+ % connect to connect a slot. Then, whenever the emit method is
+ % called, all connected methods get called.
+
+ % Attribute
+ \attribute emitter;%
+ % Collects the objects that should be called.
+
+ % Constructor
+ \method signal() {}%
+
+ % Connect a slot (method) #2 of object #1
+ \method connect(#1,#2) {%
+ {%
+ #1.get id(\pgf@tempid)%
+ % Save in emitter
+ \pgfooget{emitter}\pgf@temp%
+ \let\pgfoo@signal@call=\relax% avoid expansion
+ \edef\pgf@temp{\pgf@temp\pgfoo@signal@call{\pgf@tempid}{#2}}%
+ \pgfoolet{emitter}\pgf@temp%
+ }%
+ }%
+
+ \def\pgfoo@signal@call#1#2{%
+ \def\pgf@temp{\pgfooobj{#1}.#2}%
+ \expandafter\pgf@temp\expandafter(\pgfoo@signal@args)%
+ }%
+
+ % Emit a signal
+ \method emit(#1) {%
+ \def\pgfoo@signal@args{#1}%
+ \pgfoovalueof{emitter}
+ }%
+}%
+
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduleparser.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduleparser.code.tex
new file mode 100644
index 0000000000..ca2a597560
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduleparser.code.tex
@@ -0,0 +1,697 @@
+% Copyright 2019 by Till Tantau
+% Copyright 2019 by Jonathan P. Spratte
+%
+% 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{pgfmoduleparser.code.tex}
+
+%
+% This file defines commands for defining a letter-by-letter parser
+% based on a dfa. The idea is inspired by the pgf module parser, but extends it
+% and eventually replaced it.
+%
+
+% options
+\long\def\pgfparserset#1%
+ {%
+ \pgfqkeys{/pgfparser}{#1}%
+ }
+\pgfparserset
+ {%
+ ,silent/.is if=\pgfparser@ifname{every parser silent}%
+ ,status/.is if=\pgfparser@ifname{pgfparser status}%
+ }
+
+% logic helpers
+\long\def\pgfparser@fi@Bn\fi#1{\fi}
+\long\def\pgfparser@fi@Bg\fi#1#2{\fi}
+\long\def\pgfparser@fi@BTb\fi#1#2#3{\fi#2}
+\long\def\pgfparser@fi@BTc\fi#1#2#3{\fi#3}
+
+% opt arg parsing
+\long\def\pgfparserifmark#1%
+ {%
+ \ifx\pgfparser@mark#1%
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@oarg#1%
+ {%
+ \pgfutil@ifnextchar[{\pgfparser@oarg@oarg@{#1}}{#1{\pgfparser@mark}}%
+ }
+\long\def\pgfparser@oarg@oarg@#1[#2]%
+ {%
+ #1{#2}%
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@Oarg#1#2%
+ {%
+ \pgfutil@ifnextchar[{\pgfparser@oarg@oarg@{#2}}{#2{#1}}%
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@darg#1#2#3%
+ {%
+ \long\def\pgfparser@oarg@darg@##1#1##2#2{##1{##2}}%
+ \pgfutil@ifnextchar#1{\pgfparser@oarg@darg@{#3}}{#3{\pgfparser@mark}}%
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@Darg#1#2#3#4%
+ {%
+ \long\def\pgfparser@oarg@darg@##1#1##2#2{##1{##2}}%
+ \pgfutil@ifnextchar#1{\pgfparser@oarg@darg@{#4}}{#4{#3}}%
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@targ@#1%
+ {%
+ \def\pgfparser@oarg@targ@next{#1}%
+ \afterassignment\pgfparser@oarg@targ@next
+ \let\pgfparser@ignored@token=%
+ }
+\pgfutil@protected\long\def\pgfparser@oarg@targ#1#2%
+ {%
+ \pgfutil@ifnextchar#1%
+ {\pgfparser@oarg@targ@{#2{\pgfparser@mark}}}{#2{\pgfparser@stop}}%
+ }
+
+% status messages
+\pgfutil@protected\def\pgfparser@msg#1%
+ {%
+ \immediate\write0{(pgfparser) #1}%
+ }
+\pgfutil@protected\def\pgfparser@status@start#1%
+ {%
+ \pgfparser@if{pgfparser status}{\pgfparser@msg{parser '#1' started}}{}%
+ }
+\pgfutil@protected\def\pgfparser@status@state#1%
+ {%
+ \pgfparser@if{pgfparser status}
+ {\pgfparser@msg{|= switched to state '#1'}}
+ {}%
+ }
+\pgfutil@protected\def\pgfparser@status@rule
+ {%
+ \pgfparser@if{pgfparser status}
+ {\pgfparser@msg{| \space|= rule '\meaning\pgfparsertoken' executed}}
+ {}%
+ }
+\pgfutil@protected\def\pgfparser@status@rule@all
+ {%
+ \pgfparser@if{pgfparser status}
+ {%
+ \pgfparser@msg
+ {| \space|= (all) rule '\meaning\pgfparsertoken' executed}%
+ }
+ {}%
+ }
+\pgfutil@protected\def\pgfparser@status@rule@undefined
+ {%
+ \pgfparser@if{pgfparser status}
+ {%
+ \pgfparser@msg
+ {| \space|= unknown for '\meaning\pgfparsertoken' executed}%
+ }
+ {}%
+ }
+\pgfutil@protected\def\pgfparser@status@rule@undefined@all
+ {%
+ \pgfparser@if{pgfparser status}
+ {%
+ \pgfparser@msg
+ {| \space|= (all) unknown for '\meaning\pgfparsertoken' executed}%
+ }
+ {}%
+ }
+
+% macros for string comparison
+\begingroup
+\lccode`\P=`\P \lccode`\G=`\G \lccode`\F=`\F
+\lccode`\:=`\X \lccode`\;=`\r \lccode`\A=`\-
+\lowercase
+ {%
+ \endgroup
+ \def\pgfparser@mark{APGFparse;:mark-}%
+ \def\pgfparser@stop{APGFparse;:stop-}%
+ }%
+\def\pgfparser@final{final}
+\def\pgfparser@noarg{noarg}
+\def\pgfparser@blankspace{blank space}
+
+% counters
+\newcount\pgfparserdef@arg@count
+
+% shortcuts for special names
+\def\pgfparser@name#1%
+ {%
+ pgfparser #1%
+ }
+\def\pgfparser@rule#1%
+ {%
+ \pgfparser@current\space #1\space \meaning\pgfparsertoken
+ }
+\def\pgfparser@type#1%
+ {%
+ \pgfparser@rule{#1} type%
+ }
+\def\pgfparser@code#1%
+ {%
+ \pgfparser@rule{#1} code%
+ }
+\def\pgfparser@undefined#1%
+ {%
+ \pgfparser@current\space #1\space unknown%
+ }
+\def\pgfparser@ifname#1%
+ {%
+ pgfparserconditional #1%
+ }
+
+% conditionals
+\def\pgfparser@if#1%
+ {%
+ \pgfutil@ifundefined{if\pgfparser@ifname{#1}}
+ {%
+ \pgferror{Undefined conditional '#1'. Falling back to false}%
+ \iffalse
+ }
+ {\csname if\pgfparser@ifname{#1}\endcsname}%
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ }
+\def\pgfparser@newif#1%
+ {%
+ \csname newif\expandafter\endcsname
+ \csname if\pgfparser@ifname{#1}\endcsname
+ }
+\pgfparser@newif{every parser silent}
+\pgfparser@newif{pgfparserdef abort}
+\pgfparser@newif{pgfparser status}
+
+% pgfparserdef
+\pgfutil@protected\def\pgfparserdef#1#2%
+ {%
+ \def\pgfparserdef@twoargs{{#1}{#2}}%
+ \pgfparserdef@a
+ }
+\pgfutil@protected\def\pgfparserdef@a
+ {%
+ \futurelet\pgfparserdef@arg\pgfparserdef@b
+ }
+\def\pgfparserdef@b
+ {%
+ \ifx\pgfparserdef@arg\pgfutil@sptoken
+ % will also gobble the \pgfparserdef@c after \fi
+ \pgfparserdef@gobble@space
+ \fi
+ \pgfparserdef@c
+ }
+\pgfutil@protected\def\pgfparserdef@gobble@space\fi#1%
+ {%
+ \fi
+ \afterassignment\pgfparserdef@a
+ \let\pgfparser@ignored@token= % space after = to get spaces, too
+ }
+\pgfutil@protected\def\pgfparserdef@c#1%
+ {%
+ \ifx\pgfparserdef@arg\bgroup
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {%
+ \def\pgfparserdef@arg{#1}%
+ \ifx\pgfparser@blankspace\pgfparserdef@arg
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {\expandafter\pgfparserdef@d\pgfparserdef@twoargs{blank space \space}}
+ {\expandafter\pgfparserdef@d\pgfparserdef@twoargs{#1}}%
+ }
+ {%
+ \expandafter\pgfparserdef@d\pgfparserdef@twoargs
+ {\meaning\pgfparserdef@arg}%
+ }%
+ }
+\long\def\pgfparserdef@d#1#2#3%
+ {%
+ \pgfparser@oarg@Oarg{}{\pgfparserdef@e{#1}{#2}{#3}}%
+ }
+\pgfutil@protected\long\def\pgfparserdef@e#1#2#3#4#5%
+ {%
+ \pgfparser@initiate@parser{#1}%
+ \csname\pgfparser@ifname{pgfparserdef abort}false\endcsname
+ % check how many arguments are used, also parses whether the argument string
+ % is valid
+ \pgfparserdef@arg@count=0
+ \pgfparserdef@argcount#4\pgfparser@mark
+ \ifnum\pgfparserdef@arg@count>9
+ \pgferror
+ {%
+ Too many arguments for parser rule. A maximum of 9 parameters is
+ supported.%
+ }%
+ \csname\pgfparser@ifname{pgfparserdef abort}true\endcsname
+ \fi
+ % define what the code does
+ \pgfparser@if{pgfparserdef abort}{}
+ {%
+ % use a macro as flag that there is a rule for the specified state and
+ % hold information how to parse it
+ \ifnum\pgfparserdef@arg@count=0
+ \pgfutil@namedef{\pgfparser@name{#1} #2 #3 type}{noarg}%
+ \pgfutil@namedef{\pgfparser@name{#1} #2 #3 code}%
+ {#5\pgfparser@getnexttoken}%
+ \else
+ \pgfutil@namedef{\pgfparser@name{#1} #2 #3 type}{#4}%
+ \expandafter\pgfparserdef@argstring@def\the\pgfparserdef@arg@count
+ \pgfutil@namedef{\pgfparser@name{#1} #2 #3 code\expandafter}%
+ \pgfparserdef@argstring##1##2##3##4##5##6##7##8##9%
+ {#5\pgfparser@getnexttoken}%
+ \fi
+ }%
+ }
+\def\pgfparserdef@argstring@def#1%
+ {%
+ \def\pgfparserdef@argstring##1#1##2##{##1#1}%
+ }
+\def\pgfparserdef@argcount#1%
+ {%
+ \ifx\pgfparser@mark#1%
+ \pgfparser@fi@Bg
+ \fi
+ \pgfutil@firstofone
+ {%
+ \pgfutil@IfUndefined{pgfparserdef@argcount@#1}
+ {%
+ \pgferror{Unknown argument type '#1'. Aborting rule definition}%
+ \pgfparserdef@argcount@abort
+ }
+ {\csname pgfparserdef@argcount@#1\endcsname}%
+ }%
+ }
+\pgfutil@protected\long\def\pgfparserdef@argcount@abort#1\pgfparser@mark
+ {%
+ \csname\pgfparser@ifname{pgfparserdef abort}true\endcsname
+ }
+\def\pgfparserdef@argcount@m
+ {%
+ \advance\pgfparserdef@arg@count1
+ \pgfparserdef@argcount
+ }
+\let\pgfparserdef@argcount@o\pgfparserdef@argcount@m
+\def\pgfparserdef@argcount@O#1%
+ {%
+ \advance\pgfparserdef@arg@count1
+ \pgfparserdef@argcount
+ }
+\let\pgfparserdef@argcount@r\pgfparserdef@argcount@O
+\let\pgfparserdef@argcount@t\pgfparserdef@argcount@O
+\def\pgfparserdef@argcount@d#1#2%
+ {%
+ \advance\pgfparserdef@arg@count1
+ \pgfparserdef@argcount
+ }
+\def\pgfparserdef@argcount@D#1#2#3%
+ {%
+ \advance\pgfparserdef@arg@count1
+ \pgfparserdef@argcount
+ }
+
+\pgfutil@protected\def\pgfparser@initiate@parser#1%
+ {%
+ % if that is the first rule for the parser
+ \pgfutil@IfUndefined{if\pgfparser@ifname{#1 silent}}%
+ {%
+ % define space to be a no-op
+ \pgfutil@namedef
+ {\pgfparser@name{#1} all blank space \space\space type}{noarg}%
+ \pgfutil@namedef
+ {\pgfparser@name{#1} all blank space \space\space code}%
+ {\pgfparser@getnexttoken}%
+ % define a new conditional whether the parser silently ignores unknown
+ % tokens
+ \pgfparser@newif{#1 silent}%
+ \pgfparserset
+ {%
+ #1/silent/.is if=\pgfparser@ifname{#1 silent}%
+ }%
+ }
+ {}%
+ }
+
+% pgfparserlet
+\pgfutil@protected\def\pgfparserlet#1#2%
+ {%
+ \def\pgfparserlet@parser@a{#1}%
+ \def\pgfparserlet@state@a{#2}%
+ \pgfparserlet@a
+ }
+\pgfutil@protected\def\pgfparserlet@a
+ {%
+ \futurelet\pgfparserlet@arga\pgfparserlet@b
+ }
+\def\pgfparserlet@b
+ {%
+ \ifx\pgfparserlet@arga\pgfutil@sptoken
+ % will also gobble the \pgfparserlet@c after \fi
+ \pgfparserlet@gobble@space\pgfparserlet@a
+ \fi
+ \pgfparserlet@c
+ }
+\pgfutil@protected\def\pgfparserlet@gobble@space#1\fi#2%
+ {%
+ \fi
+ \afterassignment#1%
+ \let\pgfparser@ignored@token= % space after = to get spaces, too
+ }
+\pgfutil@protected\def\pgfparserlet@c#1%
+ {%
+ \ifx\pgfparserlet@arga\bgroup
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {%
+ \def\pgfparserlet@arga{#1}%
+ \ifx\pgfparser@blankspace\pgfparserlet@arga
+ \def\pgfparserlet@arga{blank space \space}%
+ \fi
+ }
+ {\edef\pgfparserlet@arga{\meaning\pgfparserlet@arga}}%
+ \pgfparser@oarg@oarg\pgfparserlet@d
+ }
+\pgfutil@protected\def\pgfparserlet@d#1%
+ {%
+ \pgfparserifmark{#1}
+ {%
+ \let\pgfparserlet@parser@b\pgfparserlet@parser@a
+ \let\pgfparserlet@state@b\pgfparserlet@state@a
+ \pgfparserlet@f
+ }
+ {\pgfparser@oarg@oarg{\pgfparserlet@e{#1}}}%
+ }
+\pgfutil@protected\def\pgfparserlet@e#1#2%
+ {%
+ \pgfparserifmark{#2}
+ {%
+ \let\pgfparserlet@parser@b\pgfparserlet@parser@a
+ \def\pgfparserlet@state@b{#1}%
+ }
+ {%
+ \def\pgfparserlet@parser@b{#1}%
+ \def\pgfparserlet@state@b{#2}%
+ }
+ \pgfparserlet@f
+ }
+\pgfutil@protected\def\pgfparserlet@f
+ {%
+ \futurelet\pgfparserlet@argb\pgfparserlet@g
+ }
+\def\pgfparserlet@g
+ {%
+ \ifx\pgfparserlet@argb\pgfutil@sptoken
+ % will also gobble the \pgfparserlet@h after \fi
+ \pgfparserlet@gobble@space\pgfparserlet@f
+ \fi
+ \pgfparserlet@h
+ }
+\pgfutil@protected\def\pgfparserlet@h#1%
+ {%
+ \ifx\pgfparserlet@argb\bgroup
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {%
+ \def\pgfparserlet@argb{#1}%
+ \ifx\pgfparser@blankspace\pgfparserlet@argb
+ \def\pgfparserlet@argb{blank space \space}%
+ \fi
+ }
+ {\edef\pgfparserlet@argb{\meaning\pgfparserlet@argb}}%
+ \pgfparserlet@i
+ \pgfparserlet@parser@a
+ \pgfparserlet@state@a
+ \pgfparserlet@arga
+ \pgfparserlet@parser@b
+ \pgfparserlet@state@b
+ \pgfparserlet@argb
+ }
+\def\pgfparserlet@i#1#2#3#4#5#6%
+ {%
+ \pgfutil@IfUndefined{\pgfparser@name{#4} #5 #6 type}
+ {%
+ \pgferror
+ {%
+ There is no rule defined for parser '#4' in state '#5' for '#6'.
+ Aborting \string\pgfparserlet
+ }%
+ }
+ {%
+ \pgfparser@initiate@parser{#1}%
+ \pgfparserlet@let{#1}{#2}{#3}{#4}{#5}{#6}{type}%
+ \pgfparserlet@let{#1}{#2}{#3}{#4}{#5}{#6}{code}%
+ }%
+ }
+\def\pgfparserlet@let#1#2#3#4#5#6#7%
+ {%
+ \expandafter\let\csname\pgfparser@name{#1} #2 #3 #7\expandafter\endcsname
+ \csname\pgfparser@name{#4} #5 #6 #7\endcsname
+ }
+
+\pgfutil@protected\long\def\pgfparserdefunknown#1#2#3%
+ {%
+ \pgfparser@initiate@parser{#1}%
+ \pgfutil@namedef{\pgfparser@name{#1} #2 unknown}{#3}%
+ }
+\pgfutil@protected\long\def\pgfparserdeffinal#1#2%
+ {%
+ \pgfutil@namedef{\pgfparser@name{#1} final action}{#2}%
+ }
+\pgfutil@protected\def\pgfparserswitch#1%
+ {%
+ \pgfparser@status@state{#1}%
+ \def\pgfparserstate{#1}%
+ }
+\pgfutil@protected\def\pgfparserparse#1%
+ {%
+ \pgfutil@IfUndefined{if\pgfparser@ifname{#1 silent}}
+ {\pgferror{No parser named '#1' defined}}
+ {%
+ \edef\pgfparser@current{\pgfparser@name{#1}}%
+ \def\pgfparser@usersname{#1}%
+ \pgfparser@status@start{#1}%
+ \pgfparserswitch{initial}%
+ \pgfparser@getnexttoken
+ }%
+ }
+% get next token
+\pgfutil@protected\def\pgfparser@getnexttoken
+ {%
+ \ifx\pgfparserstate\pgfparser@final
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {%
+ \pgfutil@IfUndefined{\pgfparser@current\space final action}
+ {}
+ {\csname \pgfparser@current\space final action\endcsname}%
+ }
+ {\futurelet\pgfparsertoken\pgfparser@getnexttoken@a}%
+ }
+\pgfutil@protected\def\pgfparser@getnexttoken@a
+ {%
+ % check the problematic categories based on the meaning of the token
+ \edef\pgfparser@tokencategory{\pgfparser@extractmeaning\pgfparsertoken}%
+ \pgfparser@getnexttoken@ifcategory\pgfparser@category@i\bgroup
+ {%
+ \pgfparser@getnexttoken@ifcategory\pgfparser@category@ii\egroup
+ {%
+ \pgfparser@getnexttoken@ifcategory\pgfparser@category@x{ }%
+ {%
+ \pgfparser@getnexttoken@ifcategory\pgfparser@category@vi{####}%
+ {\pgfparser@getnexttoken@defchar}%
+ }%
+ }%
+ }%
+ }
+\begingroup
+\def\pgfparser@extractmeaning#1%
+ {%
+ \endgroup
+ \def\pgfparser@extractmeaning##1%
+ {\expandafter\pgfparser@extractmeaning@\meaning##1#1#1\pgfparser@mark}%
+ \def\pgfparser@extractmeaning@##1#1##2#1##3\pgfparser@mark{##1#1##2}%
+ }
+\catcode`\ =12\pgfparser@extractmeaning{ } % ends the group
+\edef\pgfparser@category@i{\pgfparser@extractmeaning\bgroup}
+\edef\pgfparser@category@ii{\pgfparser@extractmeaning\egroup}
+\edef\pgfparser@category@vi{\pgfparser@extractmeaning#}
+\edef\pgfparser@category@x{\pgfparser@extractmeaning\pgfutil@sptoken}
+\pgfutil@protected\def\pgfparser@getnexttoken@ifcategory#1#2%
+ {%
+ \ifx\pgfparser@tokencategory#1%
+ \def\pgfparserletter{#2}%
+ \pgfparser@getnexttoken@gobble
+ \fi
+ \pgfutil@firstofone
+ }
+\pgfutil@protected\def\pgfparser@getnexttoken@gobble\fi#1#2%
+ {%
+ \fi
+ \afterassignment\pgfparser@getnexttoken@b
+ \let\pgfparser@ignored@token= % gobble should gobble a space
+ }
+\pgfutil@protected\long\def\pgfparser@getnexttoken@defchar#1%
+ {%
+ \def\pgfparserletter{#1}%
+ \pgfparser@getnexttoken@b
+ }
+\pgfutil@protected\def\pgfparser@getnexttoken@b
+ {%
+ \pgfutil@IfUndefined{\pgfparser@type{\pgfparserstate}}
+ {%
+ \pgfutil@IfUndefined{\pgfparser@type{all}}
+ {%
+ \pgfparser@if{every parser silent}{}
+ {%
+ \pgfparser@if{\pgfparser@usersname\space silent}{}
+ {%
+ \pgferror
+ {%
+ No rule for parser '\pgfparser@usersname' in state
+ '\pgfparserstate' for '\meaning\pgfparsertoken'.
+ Ignoring token%
+ }%
+ }%
+ }%
+ \pgfutil@IfUndefined{\pgfparser@undefined{\pgfparserstate}}
+ {%
+ \pgfutil@IfUndefined{\pgfparser@undefined{all}}
+ {}
+ {%
+ \pgfparser@status@rule@undefined@all
+ \csname\pgfparser@undefined{all}\endcsname
+ }%
+ }
+ {%
+ \pgfparser@status@rule@undefined
+ \csname\pgfparser@undefined{\pgfparserstate}\endcsname
+ }%
+ \pgfparser@getnexttoken
+ }
+ {%
+ \pgfparser@status@rule@all
+ \pgfparser@handle{all}%
+ }%
+ }
+ {%
+ \pgfparser@status@rule
+ \pgfparser@handle{\pgfparserstate}%
+ }%
+ }
+
+% handle arguments
+\pgfutil@protected\def\pgfparser@handle#1%
+ {%
+ \expandafter\ifx\csname\pgfparser@type{#1}\endcsname\pgfparser@noarg
+ \pgfparser@fi@BTb
+ \fi
+ \pgfutil@secondoftwo
+ {\csname\pgfparser@code{#1}\endcsname}
+ {\pgfparser@handle@args{#1}}%
+ }
+\pgfutil@protected\def\pgfparser@handle@args#1%
+ {%
+ \def\pgfparser@stateorall{#1}%
+ \expandafter\expandafter\expandafter\pgfparser@handle@args@a
+ \csname\pgfparser@type{#1}\endcsname\pgfparser@mark\pgfparser@stop
+ }
+\def\pgfparser@handle@args@a
+ {%
+ \pgfparser@handle@args@b{}%
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@b#1#2#3\pgfparser@stop
+ {%
+ \pgfparserifmark{#2}
+ {\csname\pgfparser@code{\pgfparser@stateorall}\endcsname#1}
+ {%
+ \pgfutil@IfUndefined{pgfparser@handle@args@#2}
+ {\pgferror{Unknown argument type '#2'}}
+ {\csname pgfparser@handle@args@#2\endcsname{#1}{#3}}%
+ }%
+ }
+\long\def\pgfparser@handle@args@c#1#2%
+ {%
+ \pgfparserifmark{#2}
+ {\csname\pgfparser@code{\pgfparser@stateorall}\endcsname#1}
+ {\pgfparser@handle@args@b{#1}#2\pgfparser@stop}%
+ }
+\long\def\pgfparser@handle@args@m#1#2#3%
+ {%
+ \pgfparser@handle@args@c{#1{#3}}{#2}%
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@o#1#2%
+ {%
+ \pgfparser@oarg@oarg{\pgfparser@handle@args@m{#1}{#2}}%
+ }
+\long\def\pgfparser@handle@args@O#1#2%
+ {%
+ \pgfparser@handle@args@O@{#1}#2\pgfparser@stop
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@O@#1#2#3\pgfparser@stop
+ {%
+ \pgfparser@oarg@Oarg{#2}{\pgfparser@handle@args@m{#1}{#3}}%
+ }
+\long\def\pgfparser@handle@args@d#1#2%
+ {%
+ \pgfparser@handle@args@d@{#1}#2\pgfparser@stop
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@d@#1#2#3#4\pgfparser@stop
+ {%
+ \pgfparser@oarg@darg{#2}{#3}{\pgfparser@handle@args@m{#1}{#4}}%
+ }
+\long\def\pgfparser@handle@args@D#1#2%
+ {%
+ \pgfparser@handle@args@D@{#1}#2\pgfparser@stop
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@D@#1#2#3#4#5\pgfparser@stop
+ {%
+ \pgfparser@oarg@Darg{#2}{#3}{#4}{\pgfparser@handle@args@m{#1}{#5}}%
+ }
+\long\def\pgfparser@handle@args@r#1#2%
+ {%
+ \pgfparser@handle@args@r@a{#1}#2\pgfparser@stop
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@r@a#1#2#3\pgfparser@stop
+ {%
+ \def\pgfparser@handle@args@r@b##1#2%
+ {\pgfparser@handle@args@c{#1{##1}}{#3}}%
+ \pgfparser@handle@args@r@b
+ }
+\long\def\pgfparser@handle@args@t#1#2%
+ {%
+ \pgfparser@handle@args@t@{#1}#2\pgfparser@stop
+ }
+\pgfutil@protected\long\def\pgfparser@handle@args@t@#1#2#3\pgfparser@stop
+ {%
+ \pgfparser@oarg@targ{#2}{\pgfparser@handle@args@m{#1}{#3}}%
+ }
+
+\pgfutil@protected\long\def\pgfparserreinsert#1%
+ {%
+ \ifx\pgfparser@getnexttoken#1%
+ \pgfparser@fi@BTb
+ \fi
+ \@secondoftwo
+ {\expandafter\pgfparser@getnexttoken\pgfparserletter}
+ {%
+ \pgferror
+ {%
+ Misuse of \string\pgfparserreinsert\space detected. You should only
+ use it at the the end of an action code%
+ }%
+ #1%
+ }%
+ }
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduleplot.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduleplot.code.tex
new file mode 100644
index 0000000000..0afea0ae34
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduleplot.code.tex
@@ -0,0 +1,561 @@
+% 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{pgfmoduleplot.code.tex}
+
+
+% PGF's plotting interface works as follows:
+%
+% In order to plot something, two things need to be done. First, you
+% need to provide the coordinates (obviously) of the points that
+% should be plotted. The coordinates are given via a long stream of
+% commands. These commands are \pgfplotstreamstart, which is
+% given exactly once at the beginning, the commands
+% \pgfplotstreampoint, \pgfplotstreampointoutlier,
+% \pgfplotstreampointundefined, \pgfplotstreamnewdataset, of which
+% there are numerous in the middle, the special \pgfplotstreamspecial,
+% of which there may be numerous in the middle, and \pgfplotstreamend,
+% which must be given at the end. Between these commands arbitrary
+% other commands may be given. Here is an example:
+%
+% ...
+% \pgfplotstreamstart
+% \pgfplotstreampoint{\pgfpointxy{0}{0}}
+% \pgfplotstreampoint{\pgfpointxy{1}{1}}
+% \pgfplotstreamnewdataset
+% \pgfplotstreampoint{\pgfpointxy{2}{4}}
+% \relax
+% \pgfplotstreampointoutlier{\pgfpointxy{3}{9}}
+% \pgfplotstreamspecial{some handler-dependent special stuff}
+% \pgfplotstreamend
+%
+% By themselves, the \pgfplotstreamxxxx commands do not do anything by
+% default. Rather, to ``use'' such a stream, you must first install a
+% stream handler. For example, the ``lineto'' handler will simply
+% basically every \pgfplotstreampoint into a \pgfpathlineto.
+%
+% One special things is the handling of "jumps" in a stream. For
+% instance, when a lineto handler encounters an "outlier" or a new
+% data set, the current line should end and a new subpath should start
+% (unless configured otherwise). For this, the special jump handler is
+% important.
+%
+% Example:
+%
+% \pgfpathmoveto{\pgfpointorigin}
+%
+% \pgfplothandlerlineto
+% \pgfplotstreamstart
+% \pgfplotstreampoint{\pgfpointxy{0}{0}}
+% \pgfplotstreampoint{\pgfpointxy{1}{1}}
+% \pgfplotstreampoint{\pgfpointxy{2}{4}}
+% \relax
+% \pgfplotstreampoint{\pgfpointxy{3}{9}}
+% \pgfplotstreamend
+
+
+% The stream commands actually call their ``internal'' versions, which
+% are set by the handlers:
+\def\pgfplotstreamstart{\pgf@plotstreamstart}%
+\def\pgfplotstreampoint#1{\gdef\pgfplotlastpoint{#1}\pgf@plotstreampoint{#1}}%
+\def\pgfplotstreampointoutlier#1{\pgfplot@outliers{}{\pgf@plotstreamjump}{\pgfplotstreampoint{#1}}}%
+\def\pgfplotstreampointundefined{\pgfplot@outliers{}{\pgf@plotstreamjump}{}}%
+\def\pgfplotstreamnewdataset{\pgfplot@outliers{}{\pgf@plotstreamjump}{}}%
+\def\pgfplotstreamspecial{\pgf@plotstreamspecial}%
+\def\pgfplotstreamend{\pgf@plotstreamend}%
+
+\def\pgfplot@ignorer#1#2#3{#1}%
+\def\pgfplot@jumper#1#2#3{#2}%
+\def\pgfplot@plotter#1#2#3{#3}%
+
+\let\pgfplot@outliers\pgfplot@jumper
+\let\pgfplot@undefined\pgfplot@jumper
+\let\pgfplot@newdata\pgfplot@jumper
+
+\pgfset{
+ handle outlier points in plots/.is choice,
+ handle outlier points in plots/ignore/.code=\let\pgfplot@outliers\pgfplot@ignorer,
+ handle outlier points in plots/jump/.code=\let\pgfplot@outliers\pgfplot@jumper,
+ handle outlier points in plots/plot/.code=\let\pgfplot@outliers\pgfplot@plotter,
+ handle undefined points in plots/.is choice,
+ handle undefined points in plots/ignore/.code=\let\pgfplot@undefined\pgfplot@ignorer,
+ handle undefined points in plots/jump/.code=\let\pgfplot@undefined\pgfplot@jumper,
+ handle new data sets in plots/.is choice,
+ handle new data sets in plots/ignore/.code=\let\pgfplot@newdata\pgfplot@ignorer,
+ handle new data sets in plots/jump/.code=\let\pgfplot@newdata\pgfplot@jumper,
+}%
+
+
+% Declares a new plot handler
+%
+% #1 = macro that should install the stream handler subsequently
+% #2 = parameter list of said macro.
+% #3 = keys as described below
+%
+% Description:
+%
+% When you declare a new plot handler, you provide, through keys,
+% different "actions" that should be taken when the different stream
+% commands are used:
+%
+% start = some code to be executed when \pgfplotstreamstart is called
+% for this plothandler
+% end = same for the end of the stream
+% point = code to be executed for a point of the stream
+% jump = code to be executed for a "jump" in the stream
+% special = code to be executed for \pgfplotstreamspecial
+% start macro = here and for the following keys, the to-be-executed
+% code is stored in the given macro
+% end macro = see above
+% jump macro = see above
+% point macro = see above
+% special macro = see above
+%
+% Example:
+%
+% \pgfdeclareplothandler{\ultrasimplehandler}{}{
+% point=\pgfpathlineto{##1}
+% }
+
+\def\pgfdeclareplothandler#1#2#3{%
+ \def#1#2{%
+ \pgfkeys{%
+ /pgf/plots/@handler options/.cd,
+ start=\relax,
+ end macro=\relax,
+ point macro=\pgfutil@gobble,
+ jump macro=\relax,
+ special macro=\pgfutil@gobble,%
+ #3%
+ }%
+ }%
+}%
+
+\pgfkeys{%
+ /pgf/plots/@handler options/.cd,
+ start/.code=%
+ \gdef\pgf@plotstreamstart{%
+ \global\pgf@plot@startedfalse%
+ \global\let\pgf@plotstreamend\pgf@plotstreamend@init%
+ \global\let\pgf@plotstreampoint\pgf@plotstreampoint@init%
+ \global\let\pgf@plotstreamjump\pgf@plotstreamjump@init%
+ \global\let\pgf@plotstreamspecial\pgf@plotstreamspecial@init%
+ #1%
+ },%
+ start macro/.code=%
+ \gdef\pgf@plotstreamstart{%
+ \global\pgf@plot@startedfalse%
+ \global\let\pgf@plotstreamend\pgf@plotstreamend@init%
+ \global\let\pgf@plotstreampoint\pgf@plotstreampoint@init%
+ \global\let\pgf@plotstreamjump\pgf@plotstreamjump@init%
+ \global\let\pgf@plotstreamspecial\pgf@plotstreamspecial@init%
+ #1%
+ },%
+ end/.code=\gdef\pgf@plotstreamend@init{#1},
+ end macro/.code=\global\let\pgf@plotstreamend@init#1,
+ point/.code=\gdef\pgf@plotstreampoint@init##1{#1},
+ point macro/.code=\global\let\pgf@plotstreampoint@init#1,
+ jump/.code=\gdef\pgf@plotstreamjump@init{#1},
+ jump macro/.code=\global\let\pgf@plotstreamjump@init#1,
+ special/.code=\gdef\pgf@plotstreamspecial@init##1{#1},
+ special macro/.code=\global\let\pgf@plotstreamspecial@init#1,
+}%
+
+\newif\ifpgf@plot@started
+
+
+
+
+% Sets the action taken for the first point of a plot to a lineto.
+%
+% Description:
+%
+% For certain handlers it makes sense either the start a plot by
+% moving to the first point of the plot or to do a lineto to that
+% first point. Using this command this action can be set to a lineto.
+%
+% Example:
+%
+% \pgfsetlinetofirstplotpoint
+
+\def\pgfsetlinetofirstplotpoint{\let\pgf@plot@first@action=\pgfpathlineto}%
+
+
+% Sets the action taken for the first point of a plot to a moveto.
+%
+% Example:
+%
+% \pgfsetmovetofirstplotpoint
+
+\def\pgfsetmovetofirstplotpoint{\let\pgf@plot@first@action=\pgfpathmoveto}%
+
+\let\pgf@plot@first@action=\pgfpathmoveto
+
+
+
+
+%
+% Handlers
+%
+
+
+% This handler converts each plot stream command into a lineto
+% command, except for the first, which is converted to the action that
+% has previously been specified using \pgfsetlinetofirstplotpoint or
+% \pgfsetmovetofirstplotpoint.
+%
+% Example:
+%
+% \pgfplothandlerlineto
+% \pgfplotxyfile{mytable}
+
+\pgfdeclareplothandler{\pgfplothandlerlineto}{}{
+ point macro=\pgf@plot@line@handler,
+ jump=\global\let\pgf@plotstreampoint\pgf@plot@line@handler@move%
+}%
+
+\def\pgf@plot@line@handler#1{%
+ \pgf@plot@first@action{#1}%
+ \global\let\pgf@plotstreampoint=\pgfpathlineto%
+}%
+
+\def\pgf@plot@line@handler@move#1{%
+ \pgfpathmoveto{#1}%
+ \global\let\pgf@plotstreampoint=\pgfpathlineto%
+}%
+
+
+
+% This handler turns creates a series of lineto commands, with the
+% last command being a closepath, resulting in a closed path. If a
+% jump is encountered, the current subpath is closed and a new subpath
+% is started.
+%
+% Example:
+%
+% \pgfplothandlerpolygon
+% \pgfplotxyfile{mytable}
+
+\pgfdeclareplothandler{\pgfplothandlerpolygon}{}{%
+ point macro=\pgf@plot@line@handler@close,
+ jump macro=\pgf@plot@next@close@and@moveto,
+ end macro=\pgf@plot@polygon@stop
+}%
+
+\def\pgf@plot@line@handler@close#1{%
+ \pgfpathmoveto{#1}%
+ \global\pgf@plot@startedtrue%
+ \global\let\pgf@plotstreampoint=\pgfpathlineto%
+}%
+
+\def\pgf@plot@polygon@stop{%
+ \ifpgf@plot@started%
+ \pgfpathclose%
+ \fi%
+ \global\pgf@plot@startedfalse%
+}%
+
+\def\pgf@plot@next@close@and@moveto{%
+ \ifpgf@plot@started%
+ \pgfpathclose%
+ \fi%
+ \global\let\pgf@plotstreampoint\pgf@plot@line@handler@close%
+}%
+
+
+% More handlers are defined in pgflibraryplothandlers
+
+
+
+
+
+% This handler discards the plot.
+%
+% Example:
+%
+% \pgfplothandlerdiscard
+% \pgfplotxyfile{mytable}
+
+\pgfdeclareplothandler{\pgfplothandlerdiscard}{}{}%
+
+
+
+% This handler records each plot stream command to a macro. This is
+% useful if plot commands are difficult to generate and need to be
+% ``recycled'' later on.
+%
+% Example:
+%
+% \pgfplothandlerrecord{\myplot}
+% \pgfplotxyfile{mytable} % stored in \myplot now
+% \pgfplothandlerline
+% \myplot
+% \pgftransformxshift{1cm}
+% \myplot
+
+\pgfdeclareplothandler{\pgfplothandlerrecord}{#1}{%
+ start=\gdef#1{\pgfplotstreamstart},
+ point=\expandafter\gdef\expandafter#1\expandafter{#1\pgfplotstreampoint{##1}},
+ jump=\expandafter\gdef\expandafter#1\expandafter{#1\pgf@plotstreamjump},
+ special=\expandafter\gdef\expandafter#1\expandafter{#1\pgfplotstreamspecial{##1}},
+ end=\expandafter\gdef\expandafter#1\expandafter{#1\pgfplotstreamend},
+}%
+
+
+
+% Read a plot stream from a file and plot it.
+%
+% #1 = file from which to read things
+%
+% File format:
+%
+% Each line of the file should begin with two numbers separated by a
+% space. Such a line with number #1 and #2 is converted to a
+% \pgfplotstreampoint{\pgfpointxy{#1}{#2}}. Extra characters following
+% on the line are ignored.
+%
+% Lines starting with ``%'' and ``#'' are ignored.
+%
+% Example:
+%
+% \pgfplotxyfile{tableformgnuplot.dat}
+
+\def\pgfplotxyfile#1{%
+ \begingroup%
+ \def\b@pgfplotsxyfile@scanning@for@first{1}%
+ \pgfplotstreamstart%
+ \openin\r@pgf@reada=#1
+ \ifeof\r@pgf@reada
+ \pgfwarning{Plot data file `#1' not found.}
+ \else
+ \catcode`\#=14
+ \catcode`\^^M=5
+ \pgf@readxyfile%
+ \fi
+ \pgfplotstreamend%
+ \endgroup%
+}%
+
+\let\pgf@savedpar=\par
+\def\pgf@partext{\par}%
+\def\pgf@readxyfile{%
+ \pgfutil@read\r@pgf@reada to \pgf@temp%
+ \let\par=\pgf@savedpar%
+ \edef\pgf@temp{\pgf@temp}%
+ \ifx\pgf@temp\pgfutil@empty%
+ \if1\b@pgfplotsxyfile@scanning@for@first
+ \else
+ \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi%
+ \fi
+ \else\ifx\pgf@temp\pgf@partext%
+ \if1\b@pgfplotsxyfile@scanning@for@first
+ \else
+ \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi%
+ \fi
+ \else%
+ \expandafter\pgf@parsexyline\pgf@temp\pgf@stop%
+ \fi\fi%
+ \ifeof\r@pgf@reada\else\expandafter\pgf@readxyfile\fi%
+}%
+
+\def\pgf@parsexyline#1 #2 #3\pgf@stop{%
+ \def\b@pgfplotsxyfile@scanning@for@first{0}%
+ \edef\pgf@xyline@flag@val{#3}%
+ \ifx\pgf@xyline@flag@val\pgf@xyline@flag@undef%
+ \pgfplotstreampointundefined%
+ \else\ifx\pgf@xyline@flag@val\pgf@xyline@flag@out%
+ \pgfplotstreampointoutlier{\pgfpointxy{#1}{#2}}%
+ \else%
+ \pgfplotstreampoint{\pgfpointxy{#1}{#2}}%
+ \fi\fi%
+}%
+
+\edef\pgf@xyline@flag@out{o\space}%
+\edef\pgf@xyline@flag@undef{u\space}%
+
+
+
+
+% Read a plot stream from a file and plot it.
+%
+% #1 = file from which to read things
+%
+% File format:
+%
+% Like xy, except that each line contains three numbers, which are
+% converted to xyz coordinates.
+%
+% Example:
+%
+% \pgfplotxyfile{tableformgnuplot.dat}
+
+\def\pgfplotxyzfile#1{%
+ \begingroup%
+ \pgfplotstreamstart%
+ \openin\r@pgf@reada=#1
+ \ifeof\r@pgf@reada
+ \pgfwarning{Plot data file `#1' not found.}
+ \else
+ \catcode`\#=14
+ \catcode`\^^M=5
+ \pgf@readxyzfile%
+ \fi
+ \pgfplotstreamend%
+ \endgroup%
+}%
+
+\def\pgf@readxyzfile{%
+ \pgfutil@read\r@pgf@reada to \pgf@temp%
+ \ifx\pgf@temp\pgfutil@empty%
+ \if1\b@pgfplotsxyfile@scanning@for@first
+ \else
+ \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi%
+ \fi
+ \else\ifx\pgf@temp\pgf@partext%
+ \if1\b@pgfplotsxyfile@scanning@for@first
+ \else
+ \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi%
+ \fi
+ \else%
+ \expandafter\pgf@parsexyzline\pgf@temp\pgf@stop%
+ \fi\fi%
+ \ifeof\r@pgf@reada\else\expandafter\pgf@readxyzfile\fi%
+}%
+
+\def\pgf@parsexyzline#1 #2 #3 #4\pgf@stop{%
+ \def\b@pgfplotsxyfile@scanning@for@first{0}%
+ \edef\pgf@xyline@flag@val{#4}%
+ \ifx\pgf@xyline@flag@val\pgf@xyline@flag@undef%
+ \pgfplotstreampointundefined%
+ \else\ifx\pgf@xyline@flag@val\pgf@xyline@flag@out%
+ \pgfplotstreampointoutlier{\pgfpointxyz{#1}{#2}{#3}}%
+ \else%
+ \pgfplotstreampoint{\pgfpointxyz{#1}{#2}{#3}}%
+ \fi\fi%
+}%
+
+
+
+
+% Render a function using gnuplot.
+%
+% #1 = filename prefix for .gnuplot and .table files (optional,
+% default is \jobname)
+% #2 = gnuplot function text
+%
+% Description:
+%
+% This command will write a file called #1.gnuplot that sets up
+% some gnuplot commands to write output to a file called
+% #1.table. Then it calls gnuplot (using the \write18 mechanism)
+% to execute the file. Then it reads #2.table using \pgfplotxyfile.
+%
+% Example:
+%
+% \pgfplothandlerlineto
+% \pgfplotgnuplot[\jobname]{plot [x=0:5] x*sin(x)}
+
+{%
+ \catcode`\%=12
+ \catcode`\"=12
+ \xdef\pgf@gnuplot@head{set table \noexpand\pgf@plottablefile@quoted; set format "%.5f"}
+}%
+
+\let\pgf@plotwrite=\w@pgf@writea
+\newif\ifpgf@resample@plot
+
+\pgfkeys{%
+ /pgf/plot/gnuplot call/.initial={gnuplot}}%
+
+\def\pgfplotgnuplot{\pgfutil@ifnextchar[{\pgf@plotgnuplot}{\pgf@plotgnuplot[\jobname]}}%}%
+\def\pgf@plotgnuplot[#1]#2{%
+ \pgf@resample@plottrue%
+ \pgfutilpreparefilename{#1.gnuplot}%
+ \let\pgf@plotgnuplotfile=\pgfretval
+ \pgfutilpreparefilename{#1.table}%
+ \let\pgf@plottablefile=\pgfretval
+ \let\pgf@plottablefile@quoted=\pgfretvalquoted
+ % Check, whether it is up-to-date
+ \openin\pgfutil@inputcheck=\pgf@plotgnuplotfile\relax
+ \ifeof\pgfutil@inputcheck%
+ \else%
+ \pgfutil@read\pgfutil@inputcheck to\pgf@temp% ignored
+ \pgfutil@read\pgfutil@inputcheck to\pgf@plot@line%
+ \closein\pgfutil@inputcheck
+ \edef\pgf@plot@code{#2\space}%
+ \ifx\pgf@plot@code\pgf@plot@line%
+ \openin\pgfutil@inputcheck=\pgfretval\relax
+ \ifeof\pgfutil@inputcheck%
+ \else%
+ \closein\pgfutil@inputcheck
+ \pgf@resample@plotfalse%
+ \fi%
+ \fi%
+ \fi
+ \ifpgf@resample@plot%
+ \immediate\openout\pgf@plotwrite=\pgf@plotgnuplotfile\relax
+ \immediate\pgfutil@write\pgf@plotwrite{\pgf@gnuplot@head}%
+ \immediate\pgfutil@write\pgf@plotwrite{#2}%
+ \immediate\closeout\pgf@plotwrite%
+ \pgfutil@shellescape{%
+ \pgfkeysvalueof{/pgf/plot/gnuplot call} \pgf@plotgnuplotfile}%
+ \fi%
+% \let\pgf@savedparsexyline=\pgf@parsexyline%
+% \let\pgf@parsexyline=\pgf@parsegnuplotxyline%
+ \pgfplotxyfile{\pgf@plottablefile}%
+% \let\pgf@parsexyline=\pgf@savedparsexyline%
+}%
+
+% \def\pgf@parsegnuplotxyline#1 #2 #3\pgf@stop{%
+% \edef\pgf@xyline@flag@val{#3}%
+% \edef\pgf@xyline@flag@out{o\space}%
+% \edef\pgf@xyline@flag@undef{u\space}%
+% \ifx\pgf@xyline@flag@val\pgf@xyline@flag@undef%
+% \pgfplotstreampointundefined%
+% \else\ifx\pgf@xyline@flag@val\pgf@xyline@flag@out%
+% \pgfplotstreampointoutlier{\pgfpointxy{#1}{#2}}%
+% \else%
+% \pgfplotstreampoint{\pgfpointxy{#1}{#2}}%
+% \fi\fi%
+% }%
+
+% This producer handler plots a function using pgf's mathematical engine.
+%
+% #1 = variable
+% #2 = domain for the variable
+% #3 = point, typically defined in terms of the value of the variable
+%
+% Description:
+%
+% This producer will iterate the variable #1 over all variables in #2
+% (using the \foreach statement). For each value, a plot coordinate
+% #3 is created.
+%
+% Note that this command is pretty slow.
+%
+% Example:
+%
+% \pgfplothandlerlineto
+% \pgfplotfunction{\x}{0,0.1,...,3.141}{\pgfpointxy{\x}{sin(\x)}}
+
+\def\pgfplotfunction#1#2#3{%
+ \pgfplotstreamstart%
+ \foreach#1in{#2}%
+ {%
+ \pgf@process{#3}%
+ \edef\pgf@marshal{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}%
+ \pgf@marshal%
+ }
+ \pgfplotstreamend%
+}%
+
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmoduleshapes.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmoduleshapes.code.tex
new file mode 100644
index 0000000000..6be10d1464
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmoduleshapes.code.tex
@@ -0,0 +1,1334 @@
+% 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{pgfmoduleshapes.code.tex}
+
+
+
+\newbox\pgfnodeparttextbox
+
+
+% Creates a node
+%
+% #1 = shape type
+% #2 = anchor
+% #3 = name for later reference
+% #4 = path usage command
+%
+% Description:
+%
+% This command draws a shape that has previously been defined using
+% \pgfdeclareshape. The shape is shifted such that the anchor is at
+% the origin. In order to transform the whole shape, you should setup
+% pgf's transformation matrix prior to calling this command.
+%
+% When this command is called, the shape-specific TeX boxes of the
+% node must have been setup correctly.
+%
+% Example:
+%
+% \pgftransformshift{\pgfpoint{1cm}{1cm}}
+% \pgfmultipartnode{rectangle}{center}{hellonode}{\pgfusepath{stroke}}
+
+\def\pgfmultipartnode#1#2#3#4{%
+ \pgfutil@ifundefined{pgf@sh@s@#1}%
+ {\pgferror{Unknown shape ``#1''}}%
+ {%
+ {%
+ \ifpgflatenodepositioning%
+ \pgfsys@beginscope%
+ \fi%
+ \pgf@outer@adjust@hook%
+ \let\pgf@sh@savedmacros=\pgfutil@empty% MW
+ \let\pgf@sh@savedpoints=\pgfutil@empty%
+ \def\pgf@sm@shape@name{#1}% CJ % TT added prefix!
+ \csname pgf@sh@s@#1\endcsname%
+ \pgf@sh@savedpoints%
+ \pgf@sh@savedmacros% MW
+ \pgftransformshift{%
+ \pgf@sh@reanchor{#1}{#2}%
+ \pgf@x=-\pgf@x%
+ \pgf@y=-\pgf@y%
+ }%
+ \expandafter\pgfsavepgf@process\csname pgf@sh@sa@#3\endcsname{%
+ \pgf@sh@reanchor{#1}{#2}% FIXME : this is double work!
+ }%
+ % Save the saved points and the transformation matrix
+ \edef\pgf@node@name{#3}%
+ \ifpgflatenodepositioning%
+ \pgf@shapes@late@pos@begin%
+ \fi%
+ \ifx\pgf@node@name\pgfutil@empty%
+ \else%
+ \expandafter\xdef\csname pgf@sh@ns@\pgf@node@name\endcsname{#1}%
+ \edef\pgf@sh@@temp{\noexpand\gdef\expandafter\noexpand\csname pgf@sh@np@\pgf@node@name\endcsname}%
+ \expandafter\pgf@sh@@temp\expandafter{\pgf@sh@savedpoints}%
+ \edef\pgf@sh@@temp{\noexpand\gdef\expandafter\noexpand\csname pgf@sh@ma@\pgf@node@name\endcsname}% MW
+ \expandafter\pgf@sh@@temp\expandafter{\pgf@sh@savedmacros}% MW
+ \pgfgettransform\pgf@temp%
+ \expandafter\xdef\csname pgf@sh@nt@\pgf@node@name\endcsname{\pgf@temp}%
+ \expandafter\xdef\csname pgf@sh@pi@\pgf@node@name\endcsname{\pgfpictureid}%
+ \fi%
+ \pgfutil@ifundefined{pgf@sh@bbg@#1}{}
+ {{\pgfusetype{.behind background}\pgfidscope\pgfscope\csname pgf@sh@bbg@#1\endcsname\endpgfscope\endpgfidscope}}%
+ \pgfutil@ifundefined{pgf@sh@bg@#1}{%
+ \global\let\pgfpositionnodelaterpath\pgfutil@empty%
+ }%
+ {\pgfpushtype%
+ \pgfusetype{.background}\csname pgf@sh@bg@#1\endcsname%
+ \ifpgflatenodepositioning%
+ \pgfsyssoftpath@getcurrentpath\pgfpositionnodelaterpath%
+ \pgfprocessround{\pgfpositionnodelaterpath}{\pgfpositionnodelaterpath}%
+ \global\let\pgfpositionnodelaterpath\pgfpositionnodelaterpath%
+ \fi%
+ #4\pgfpoptype}%
+ \pgfutil@ifundefined{pgf@sh@fbg@#1}{}
+ {{\pgfusetype{.before background}\pgfidscope\pgfscope\csname pgf@sh@fbg@#1\endcsname\endpgfscope\endpgfidscope}}%
+ {%
+ \expandafter\pgfutil@for\expandafter\pgf@shape@com\expandafter:\expandafter=\csname pgf@sh@boxes@#1\endcsname\do{%
+ {%
+ \pgfusetype{.\pgf@shape@com}%
+ \pgftransformshift{\pgf@sh@reanchor{#1}{\pgf@shape@com}}%
+ \pgfapproximatenonlineartransformation%
+ \expandafter\pgfqboxsynced\expandafter{\csname pgfnodepart\pgf@shape@com box\endcsname}%
+ }%
+ }%
+ }%
+ \pgfutil@ifundefined{pgf@sh@bfg@#1}{}%
+ {{\pgfusetype{.behind foreground}\pgfidscope\pgfscope\csname pgf@sh@bfg@#1\endcsname\endpgfscope\endpgfidscope}}%
+ \pgfutil@ifundefined{pgf@sh@fg@#1}{}%
+ {\pgfpushtype\pgfusetype{.foreground}\csname pgf@sh@fg@#1\endcsname#4\pgfpoptype}%
+ \pgfutil@ifundefined{pgf@sh@ffg@#1}{}%
+ {{\pgfusetype{.before foreground}\pgfidscope\pgfscope\csname pgf@sh@ffg@#1\endcsname\endpgfscope\endpgfidscope}}%
+ \ifpgflatenodepositioning%
+ \pgf@shapes@late@pos@end%
+ \pgfsys@endscope%
+ \else%
+ \expandafter\pgf@nodecallback\expandafter{\pgf@node@name}%
+ \fi%
+ }%
+ }%
+}%
+\let\pgf@outer@adjust@hook\relax
+
+\def\pgf@shapes@late@pos@begin{%
+ % Rename node
+ \edef\pgf@node@name{not yet positionedPGFINTERNAL\pgf@node@name}%
+ % Interrupt bounding box!
+ \pgfinterruptboundingbox%
+ % Put everything in our box:
+ \pgf@relevantforpicturesizetrue%
+ \setbox\pgfpositionnodelaterbox=\hbox%
+ \bgroup%
+ \pgfsys@beginscope%
+}%
+
+\def\pgf@shapes@late@pos@end{%
+ \pgfsys@endscope%
+ \egroup% Close box
+ \ifdim\pgf@picminx>\pgf@picmaxx\relax% happens for empty nodes
+ \def\pgfpositionnodelaterminx{0.0pt}%
+ \let\pgfpositionnodelaterminy\pgfpositionnodelaterminx%
+ \let\pgfpositionnodelatermaxx\pgfpositionnodelaterminx%
+ \let\pgfpositionnodelatermaxy\pgfpositionnodelaterminx%
+ \else%
+ \edef\pgfpositionnodelaterminx{\the\pgf@picminx}%
+ \edef\pgfpositionnodelaterminy{\the\pgf@picminy}%
+ \edef\pgfpositionnodelatermaxx{\the\pgf@picmaxx}%
+ \edef\pgfpositionnodelatermaxy{\the\pgf@picmaxy}%
+ \fi%
+ \let\pgfpositionnodelatername=\pgf@node@name%
+ \pgf@positionnodelater@macro%
+ \endpgfinterruptboundingbox%
+}%
+
+\def\pgf@shift@node#1#2{%
+ % This internal command shifts the recorded coordinates for node #1
+ % by the vector #2. It is used to
+ % correct the position of the node if the recorded coordinate
+ % happens to be wrong
+ {%
+ \pgfsettransform{\csname pgf@sh@nt@#1\endcsname}%
+ \pgf@process{#2}%
+ \advance\pgf@pt@x by\pgf@x%
+ \advance\pgf@pt@y by\pgf@y%
+ \pgfgettransform{\pgf@temp}%
+ \expandafter\xdef\csname pgf@sh@nt@#1\endcsname{\pgf@temp}%
+ }%
+}%
+
+
+
+% Creates a node
+%
+% #1 = shape type
+% #2 = anchor
+% #3 = normal TeX text
+% #4 = name for later reference
+% #5 = path usage command
+%
+% Description:
+%
+% This command draws a shape that has previously been defined using
+% \pgfdeclareshape. The shape is shifted such that the anchor is at
+% the origin. In order to transform the whole shape, you should setup
+% pgf's transformation matrix prior to calling this command.
+%
+% Example:
+%
+% \pgftransformshift{\pgfpoint{1cm}{1cm}}
+% \pgfnode{rectangle}{center}{Hello}{hellonode}{\pgfusepath{stroke}}
+
+\def\pgfnode#1#2#3#4#5{%
+ {%
+ \setbox\pgfnodeparttextbox=\hbox%
+ {%
+ \pgfinterruptpicture%
+ {#3}%
+ \endpgfinterruptpicture%
+ }%
+ \pgfmultipartnode{#1}{#2}{#4}{#5}%
+ }
+}%
+
+
+
+% Create a node that is positioned later
+%
+% #1 = macro to be called after the next node has been created
+%
+% Description:
+%
+% You can use this command to create a node that is "positioned
+% later". The idea is the following: Normally, when a node is created
+% using a command like \pgfnode, the node is immediately inserted into
+% the current picture. In particular, you have no chance to change the
+% position of a created node after it has been create.
+%
+% Using \pgfpositionnodelater, you can change the default
+% behaviour. This command is not a replacement for \pgfnode, but is
+% called before such a command and will cause the following to happen:
+% The node is created, but not inserted into the picture. Instead, it
+% is stored in the box \pgfpositionnodelaterbox. Furthermore, the node
+% is not relevant for the picture's bounding box, but a bounding box
+% for the node is computed and stored in the macros
+% \pgfpositionnodelaterboundboxminx to
+% \pgfpositionnodelaterboundboxmaxy. Finally, the
+% macro #1 is called with the following macros setup:
+%
+% \pgfpositionnodelaterbox
+% A box register (box 0 by default) that stores the node's paths and
+% texts. You should move the contents of this box to a box of your
+% choice.
+%
+% \pgfpositionnodelatername
+% The name of the just-created-node. This name will be the
+% originally "desired" name of the box plus the prefix "not yet
+% positioned boxPGFINTERNAL".
+%
+% \pgfpositionnodelaterminx
+% \pgfpositionnodelatermaxx
+% \pgfpositionnodelaterminy
+% \pgfpositionnodelatermaxy
+% These four macros store the bounding box as dimensions that are
+% guarenteed to end with "pt".
+%
+% By setting #1 to \relax (which is the default), you can switch off
+% the whole mechanism
+%
+% Once a late node has been created, you can add arbitrary code in the
+% same picture. Then, at some later point, you call
+% \pgfpositionnodenow to finally position the node at a given position.
+%
+% When \pgfpositionnodenow is called, the macros mentioned above
+% should have the exact same values they had when #1 is called.
+
+\def\pgfpositionnodelater#1{%
+ \let\pgf@positionnodelater@macro=#1%
+ \ifx\pgf@positionnodelater@macro\relax%
+ \pgflatenodepositioningfalse%
+ \else%
+ \pgflatenodepositioningtrue%
+ \fi%
+}%
+\newif\ifpgflatenodepositioning
+\pgfpositionnodelater{\relax}%
+\def\pgfpositionnodelaterbox{0}%
+
+
+
+
+% Position a node that has been scheduled for later insertion
+%
+% #1 = position in the picture, where the original anchor should go,
+% now
+%
+% Description:
+%
+% This command works in concert with \pgfpositionnodelater, see the
+% description there. When \pgfpositionnodenow is called, the macros
+% \pgfpositionnodelaterbox and so on should be set to the values they
+% had when the macro given to \pgfpositionnodelater was called. Then,
+% the box described by these macros will be inserted into the picture
+% at the position given #1. More precisely, the original node will
+% have been positioned such that the anchor given upon invocation is
+% at (0,0) and the node is now shifted by #1 before being inserted
+% into the actual picture.
+
+\def\pgfpositionnodenow#1{%
+ \pgfinterruptpath%
+ {%
+ \pgfpointtransformed{#1}%
+ \edef\pgf@temp@shift{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
+ \pgftransformreset%
+ \pgftransformshift{\pgf@temp@shift}%
+ \pgfsys@pictureboxsynced\pgfpositionnodelaterbox%
+ \pgf@shift@node{\pgfpositionnodelatername}{\pgf@temp@shift}%
+ % Bounding box update...
+ \pgfpointtransformed{\pgfqpoint{\pgfpositionnodelaterminx}{\pgfpositionnodelaterminy}}%
+ \pgf@protocolsizes{\pgf@x}{\pgf@y}
+ \pgfpointtransformed{\pgfqpoint{\pgfpositionnodelatermaxx}{\pgfpositionnodelatermaxy}}%
+ \pgf@protocolsizes{\pgf@x}{\pgf@y}
+ % Naming and callbacks
+ \expandafter\pgfpositionnodenow@rename\pgfpositionnodelatername\relax%
+ }%
+ % Late setup%
+ {%
+ \csname pgf@lns@\pgfpositionnodelatername\endcsname%
+ \expandafter\global\expandafter\let\csname pgf@lns@\pgfpositionnodelatername\endcsname\relax%
+ }%
+ \endpgfinterruptpath%
+}%
+
+\def\pgfpositionnodenow@rename not yet positionedPGFINTERNAL#1\relax{%
+ \pgfnoderename{#1}{not yet positionedPGFINTERNAL#1}
+}%
+
+
+
+% "Fake" a node
+%
+% #1 = node name
+%
+% Description:
+%
+% This command will setup things so that it "looks like" a node named
+% #1 has been created, but, in reality, no node is created. The idea
+% is that a node created in this way can be referenced by systems
+% using the late positioning, which will only create the node later
+% on.
+%
+\def\pgffakenode#1{%
+ \edef\pgf@temp{\ifpgflatenodepositioning not yet positionedPGFINTERNAL\fi#1}%
+ \expandafter\gdef\csname pgf@sh@ns@\pgf@temp\endcsname{coordinate}%
+ \expandafter\gdef\csname pgf@sh@np@\pgf@temp\endcsname{\def\centerpoint{\pgfpointorigin}}%
+ \expandafter\gdef\csname pgf@sh@nt@\pgf@temp\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+ \expandafter\global\expandafter\let\csname pgf@sh@ma@\pgf@temp\endcsname\pgfutil@empty%
+ \expandafter\xdef\csname pgf@sh@pi@\pgf@temp\endcsname{\pgfpictureid}%
+}%
+
+
+
+% Specify code that should be executed after a node has been created
+%
+% #1 = node name
+% #2 = later code
+%
+% Description:
+%
+% This macro allows you to provide some code #2 that will be executed
+% right after a node has been positioned using \pgfpositionnodenow. If
+% the node has already been positioned (if the late positioning is not
+% switched on), nothing happens.
+
+\def\pgfnodepostsetupcode#1#2{%
+ \ifpgflatenodepositioning%
+ \expandafter\ifx\csname pgf@lns@not yet positionedPGFINTERNAL#1\endcsname\relax%
+ \expandafter\gdef\csname pgf@lns@not yet positionedPGFINTERNAL#1\endcsname{#2}%
+ \else%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@lns@not yet positionedPGFINTERNAL#1\endcsname{#2}%
+ \fi%
+ \fi%
+}%
+
+
+
+% Alias a node
+%
+% #1 = new node name
+% #2 = existing node name
+%
+% Description:
+%
+% This command allows you to subsequently access the node #2 using the
+% name #1.
+%
+% Example:
+%
+% \pgfnode{rectangle}{center}{Hallo}{hellonode}{}
+% \pgfnodealias{mynode}{hellonode}
+
+\def\pgfnodealias#1#2{%
+ \pgf@node@gnamelet{pgf@sh@ns@#1}{pgf@sh@ns@#2}%
+ \pgf@node@gnamelet{pgf@sh@np@#1}{pgf@sh@np@#2}%
+ \pgf@node@gnamelet{pgf@sh@nt@#1}{pgf@sh@nt@#2}%
+ \pgf@node@gnamelet{pgf@sh@pi@#1}{pgf@sh@pi@#2}%
+ \pgf@node@gnamelet{pgf@sh@ma@#1}{pgf@sh@ma@#2}%
+ \pgf@nodecallback{#1}%
+}%
+\def\pgf@node@gnamelet#1#2{%
+ \expandafter\let\expandafter\pgf@temp\csname #2\endcsname%
+ \expandafter\global\expandafter\let\csname #1\endcsname=\pgf@temp%
+}%
+
+% Rename a node
+%
+% #1 = new name
+% #2 = old name
+%
+% Description:
+%
+% Renames a node. This is like an alias, only the memory used for the
+% old name is freed.
+
+\def\pgfnoderename#1#2{%
+ \pgfnodealias{#1}{#2}%
+ \expandafter\global\expandafter\let\csname pgf@sh@ns@#2\endcsname\relax
+ \expandafter\global\expandafter\let\csname pgf@sh@np@#2\endcsname\relax
+ \expandafter\global\expandafter\let\csname pgf@sh@nt@#2\endcsname\relax
+ \expandafter\global\expandafter\let\csname pgf@sh@pi@#2\endcsname\relax
+ \expandafter\global\expandafter\let\csname pgf@sh@ma@#2\endcsname\relax
+}%
+
+
+
+
+% Quickly create a coordinate node
+%
+% #1 = name
+% #2 = coordinate
+%
+% Description:
+%
+% Creates a node of shape coordinate. The following have the same
+% effect, only the second is much faster:
+%
+% { \pgftransformshift{\pgfpoint{1cm}{2cm} \pgfnode{coordinate}{center}{}{foo}{} }
+% \pgfcoordinate{foo}{\pgfpoint{1cm}{2cm}}
+
+\def\pgfcoordinate#1#2{%
+ \edef\pgf@temp{#1}%
+ \ifx\pgf@temp\pgfutil@empty% do nothing
+ \else%
+ \ifpgflatenodepositioning%
+ {\pgftransformshift{#2}\pgfnode{coordinate}{center}{}{#1}{}}%
+ \else%
+ \pgf@process{\pgfpointtransformed{#2}}%
+ \expandafter\gdef\csname pgf@sh@ns@#1\endcsname{coordinate}%
+ \expandafter\xdef\csname pgf@sh@np@#1\endcsname{%
+ \noexpand\def\noexpand\centerpoint{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
+ }
+ \expandafter\gdef\csname pgf@sh@nt@#1\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+ \expandafter\global\expandafter\let\csname pgf@sh@ma@#1\endcsname\pgfutil@empty%
+ \expandafter\xdef\csname pgf@sh@pi@#1\endcsname{\pgfpictureid}%
+ \fi%
+ \fi%
+}%
+
+\def\pgf@sh@redeferredanchor#1#2{% CJ
+ \expandafter\gdef\csname pgf@anchor@\pgf@sm@shape@name @#1\endcsname{#2}}% CJ
+
+
+
+
+
+
+\def\pgf@sh@resavedanchor#1#2{%
+ \pgf@process{#2}%
+ \edef\pgf@sh@marshal{%
+ \noexpand\pgfutil@g@addto@macro\noexpand\pgf@sh@savedpoints{%
+ \noexpand\def\noexpand#1{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
+ }}%
+ \pgf@sh@marshal%
+}%
+
+
+\def\pgf@sh@resaveddimen#1#2{%
+ {#2\global\pgf@x=\pgf@x}%
+ \edef\pgf@sh@marshal{%
+ \noexpand\pgfutil@g@addto@macro\noexpand\pgf@sh@savedpoints{%
+ \noexpand\def\noexpand#1{\the\pgf@x}%
+ }}%
+ \pgf@sh@marshal%
+}%
+
+\def\pgf@sh@resavedmacro#1#2{%
+ \let#1\pgfutil@empty%
+ \def\addtosavedmacro##1{%
+ \expandafter\def\expandafter\pgf@sh@addtomacro@temp\expandafter{#1\noexpand\def\noexpand##1{##1}}%
+ {\expandafter\pgfutil@toks@\expandafter{\pgf@sh@addtomacro@temp}\expandafter}%
+ \expandafter\def\expandafter#1\expandafter{\the\pgfutil@toks@}%
+ }%
+ #2\relax%
+ \edef\pgf@sh@marshal{%
+ \noexpand\pgfutil@g@addto@macro\noexpand\pgf@sh@savedmacros{%
+ \noexpand\def\noexpand#1{#1}%
+ }}%
+ \pgf@sh@marshal%
+}%
+
+% Invoke an anchor
+\def\pgf@sh@reanchor#1#2{%
+ \pgfutil@ifundefined{pgf@anchor@#1@#2}%
+ {%
+ \pgfutil@ifundefined{pgf@anchor@generic@#2}{%
+ \pgfmathsetcounter{pgf@counta}{#2}%
+ \csname pgf@anchor@#1@border\endcsname{\pgfqpointpolar{\the\c@pgf@counta}{1pt}}%
+ }{%
+ \csname pgf@anchor@generic@#2\endcsname{#1}%
+ }%
+ }%
+ {\csname pgf@anchor@#1@#2\endcsname}%
+}%
+
+% Defines a generic anchor, i.e. one which gets the associated shape
+% as first argument.
+%
+% #1: the anchor name.
+% #2: the code of the anchor. It may depend upon '##1', the shape's
+% name.
+%
+% The anchor will be defined locally in the current TeX scope.
+%
+% If the anchor will be referenced later by \pgfpointanchor, the macro \pgfreferencednodename
+% can be used to query the referenced node's name.
+% This macro is not defined during node creation.
+\def\pgfdeclaregenericanchor#1#2{%
+ \expandafter\def\csname pgf@anchor@generic@#1\endcsname##1{#2}%
+}%
+
+
+% Retrieves an anchor of a shape
+%
+% #1 = name
+% #2 = anchor or a number (corresponding to a degree)
+%
+% Description:
+%
+% This command yields a point at the anchor of the given named shape.
+%
+% Example:
+%
+% \pgfshape{rectangle}{center}{Hello}{hellonode}{\pgfusepath[stroke]}
+% \pgfpathmoveto{\pgfpointanchor{hellonode}{center}}
+
+\def\pgfpointanchor#1#2{%
+ % Ok, check whether #1 is known!
+ \pgfutil@ifundefined{pgf@sh@ns@#1}
+ {\pgfutil@ifundefined{pgf@sh@ns@not yet positionedPGFINTERNAL#1}{%
+ \pgferror{No shape named `#1' is known}}{
+ % else, fail silently
+ }%
+ \pgfpointorigin}%
+ {%
+ \pgf@process{%
+ \edef\pgfreferencednodename{#1}% for use inside of anchors.
+ % MW install special macros
+ \csname pgf@sh@ma@#1\endcsname% MW
+ % install special coordinates
+ \csname pgf@sh@np@#1\endcsname
+ \pgf@sh@reanchor{\csname pgf@sh@ns@#1\endcsname}{#2}%
+ {%
+ \pgfsettransform{\csname pgf@sh@nt@#1\endcsname}%
+ \pgf@pos@transform@glob%
+ }%
+ % Add inter picture transformation
+ \pgf@shape@interpictureshift{#1}%
+ % Undo current transformation
+ \pgftransforminvert%
+ \pgf@pos@transform@glob%
+ }%
+ }%
+}%
+
+\def\pgf@shape@interpictureshift#1{%
+ \expandafter\ifx\csname pgf@sh@pi@#1\endcsname\pgfpictureid%
+ \else%
+ \pgfsys@getposition{\csname pgf@sh@pi@#1\endcsname}\pgf@shape@original@pos%
+ \pgfsys@getposition{\pgfpictureid}\pgf@shape@current@pos%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{\pgfpointorigin\pgf@shape@current@pos}%
+ \advance\pgf@xa by-\pgf@x%
+ \advance\pgf@ya by-\pgf@y%
+ \pgf@process{\pgfpointorigin\pgf@shape@original@pos}%
+ \advance\pgf@xa by\pgf@x%
+ \advance\pgf@ya by\pgf@y%
+ \pgf@x=\pgf@xa%
+ \pgf@y=\pgf@ya%
+ \fi%
+}%
+
+
+
+% Retrieves a border point of a shape
+%
+% #1 = name
+% #2 = another point
+%
+% Description:
+%
+% This command yields a point on the border of the shape that is on a
+% straight line from the center to the point #2.
+%
+% Example:
+%
+% \pgfshape{rectangle}{center}{Hello}{hellonode}{\pgfusepath[stroke]}
+% \pgfpathmoveto{\pgfpointshapeborder{hellonode}{\pgfpoint{2cm}{1cm}}
+% \pgfpathlineto{\pgfpoint{2cm}{1cm}}
+% \pgfusepath{stroke}
+
+\def\pgfpointshapeborder#1#2{%
+ % Ok, check whether #1 is known!
+ \pgfutil@ifundefined{pgf@sh@ns@#1}
+ {\pgferror{No shape named `#1' is known}%
+ \pgfpointorigin}%
+ {%
+ \pgf@process{%
+ \edef\pgfreferencednodename{#1}% for use inside of anchors.
+ % MW install special macros
+ \csname pgf@sh@ma@#1\endcsname% MW
+ % install special coordinates
+ \csname pgf@sh@np@#1\endcsname%
+ {%
+ \pgf@process{\pgfpointtransformed{#2}}%
+ \pgfsettransform{\csname pgf@sh@nt@#1\endcsname}%
+ \pgftransforminvert%
+ \pgf@pos@transform@glob%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{\csname pgf@anchor@\csname pgf@sh@ns@#1\endcsname @center\endcsname}%
+ \pgf@process{\pgf@shape@interpictureshift{#1}}%%
+ \advance\pgf@xa by-\pgf@x%
+ \advance\pgf@ya by-\pgf@y%
+ % Now (\pgf@xa, \pgf@ya) is a coord in shape's coord system, and
+ % relative to the anchor "center". If (xa, ya) is almost identical to
+ % the node center, which is determined by sqrt(xa^2+ya^2) < 0.02pt,
+ % just return the node center.
+ %
+ % \pgf@xb = 10*\pgf@xa if -1pt<\pgf@xa<1pt else 10pt
+ % - "10*\pgf@xa": reduce ruonding errors when \pgf@xa is small
+ % - "-1pt<\pgf@xa<1pt": guard against error "Dimension too large"
+ \pgf@xb=10pt
+ \ifdim\pgf@xa<1pt\ifdim\pgf@xa>-1pt
+ \pgf@xb=10\pgf@xa
+ \fi\fi
+ % \pgf@yb = 10*\pgf@ya if -1pt<\pgf@ya<1pt else 10pt
+ \pgf@yb=10pt
+ \ifdim\pgf@ya<1pt\ifdim\pgf@ya>-1pt
+ \pgf@yb=10\pgf@ya
+ \fi\fi
+ % if xb^2+yb^2 < 0.04pt, which means sqrt(xa^2+ya^2) < 0.02pt,
+ % return node center
+ \ifdim\dimexpr\expandafter\Pgf@geT\the\pgf@xb\pgf@xb
+ +\expandafter\Pgf@geT\the\pgf@yb\pgf@yb\relax<0.04pt
+ \expandafter\pgfutil@firstoftwo
+ \else
+ \expandafter\pgfutil@secondoftwo
+ \fi
+ {% return coord of "center"
+ \pgfwarning
+ {Returning node center instead of a point on node border. Did you
+ specify a point identical to the center of node
+ ``\pgfreferencednodename''?}%
+ \pgf@sh@reanchor{\csname pgf@sh@ns@#1\endcsname}{center}%
+ }
+ {% this calls the corresponding \anchorborder in shape declaration
+ \csname pgf@anchor@\csname pgf@sh@ns@#1\endcsname @border\endcsname
+ {\pgfqpoint{\pgf@xa}{\pgf@ya}}%
+ }%
+ \pgfsettransform{\csname pgf@sh@nt@#1\endcsname}%
+ \pgf@pos@transform@glob%
+ \global\pgf@x=\pgf@x%
+ \global\pgf@y=\pgf@y%
+ }%
+ % Add inter picture transformation
+ \pgf@shape@interpictureshift{#1}%
+ % Undo current transformation
+ \pgftransforminvert%
+ \pgf@pos@transform@glob%
+ }%
+ }%
+}%
+
+
+% Retrieve the list of node parts of a shape
+%
+% #1 = a macro
+% #2 = a shape name
+%
+% Description:
+%
+% Stores the list of node parts of a shape #2 in the macro #1.
+%
+% Example:
+%
+% \pgfgetnodeparts\mylist{circle split}
+%
+% This will set \mylist\ to "text,lower"
+
+\def\pgfgetnodeparts#1#2{%
+ \expandafter\let\expandafter#1\csname pgf@sh@boxes@#2\endcsname%
+}%
+
+
+% Declares a shape type
+%
+% #1 = shape type
+% #2 = shape specification
+%
+% Description:
+%
+% This command declares a new shape type. The shape specification
+% should contain the following commands:
+%
+% - \savedanchor
+% This command takes two arguments: a name and some code. The point
+% specified by the code (the \pgf@x and \pgf@y values resulting from
+% executing the code, to be precise), will be stored under the given
+% name. Whenever, later on, an anchor is invoked these stored points
+% will be available. The \saveddimen works like \savedanchor, only a
+% single dimension is stored (taken from \pgf@x).
+% When a savedanchor is calculated, the height/width/depth of the
+% boxes mentioned in \nodeparts can be used.
+%
+% - \anchor
+% Specifies an anchor. This command takes two arguments: an anchor
+% name and some code for computing the anchor. When the anchor
+% computation starts, all shape points and shape dimension will be
+% setup.
+%
+% - \anchorborder
+% This command should compute a point on the border of the
+% shape. When the code is called, \pgf@x and \pgf@y will have been
+% preinitialised with a direction.
+%
+% - \behindbackgroundpath
+% Some things to be draw behind everything.
+%
+% - \backgroundpath
+% A path that is drawn behind the main box. How this path is used
+% depends on how \pgfshape is called.
+%
+% - \beforebackgroundpath
+% Some things to be draw before the background path, but behind the
+% main box.
+%
+% - \behindforegroundpath
+% Some things to be draw on top of the main box.
+%
+% - \foregroundpath
+% A path that is drawn on top of all of the above. How this path is
+% used depends on how \pgfshape is called.
+%
+% - \beforeforegroundpath
+% Some things to be draw before everything.
+%
+% - \nodeparts
+% List of node parts that make up the shape. For each entry XYZ in
+% the list there must be a box named \pgfnodepartXYZbox (possibly
+% ``redirected'' to some different box using \let). Each such box
+% will be placed at the anchor XYZ.
+% By default, \nodeparts is just {text}. Thus, there will be one
+% node part box named \pgfnodeparttextbox and this node will be
+% placed at the anchor text.
+%
+%
+% Example:
+%
+% See the definition of rectangle, below.
+
+\long\def\pgfdeclareshape#1#2{%
+ {%
+ \def\pgf@sm@shape@name{#1}%
+ \let\savedanchor=\pgf@sh@savedanchor
+ \let\saveddimen=\pgf@sh@saveddimen
+ \let\savedmacro=\pgf@sh@savedmacro% MW
+ \let\deferredanchor=\pgf@sh@deferredanchor% CJ
+ \let\anchor=\pgf@sh@anchor
+ \let\anchorborder=\pgf@sh@anchorborder
+ \let\behindbackgroundpath=\pgf@sh@behindbgpath
+ \let\backgroundpath=\pgf@sh@bgpath
+ \let\beforebackgroundpath=\pgf@sh@beforebgpath
+ \let\behindforegroundpath=\pgf@sh@behindfgpath
+ \let\foregroundpath=\pgf@sh@fgpath
+ \let\beforeforegroundpath=\pgf@sh@beforefgpath
+ \let\nodeparts=\pgf@sh@boxes
+ \let\inheritsavedanchors=\pgf@sh@inheritsavedanchors
+ \let\inheritanchor=\pgf@sh@inheritanchor
+ \let\inheritanchorborder=\pgf@sh@inheritanchorborder
+ \let\inheritbehindbackgroundpath=\pgf@sh@inheritbehindbgpath
+ \let\inheritbackgroundpath=\pgf@sh@inheritbgpath
+ \let\inheritbeforebackgroundpath=\pgf@sh@inheritbeforebgpath
+ \let\inheritbehindforegroundpath=\pgf@sh@inheritbehindfgpath
+ \let\inheritforegroundpath=\pgf@sh@inheritfgpath
+ \let\inheritbeforeforegroundpath=\pgf@sh@inheritbeforefgpath
+ \let\inheritnodeparts=\pgf@sh@inheritboxes
+ \anchorborder{\csname pgf@anchor@#1@center\endcsname}%
+ \anchor{text}{\pgfpointorigin}%
+ \nodeparts{text}%
+ \expandafter\global\expandafter\let\csname pgf@sh@s@\pgf@sm@shape@name\endcsname=\pgfutil@empty%
+ #2%
+ }%
+}%
+
+\def\pgf@sh@savedanchor#1#2{%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@\pgf@sm@shape@name\endcsname{\pgf@sh@resavedanchor{#1}{#2}}}%
+\def\pgf@sh@saveddimen#1#2{%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@\pgf@sm@shape@name\endcsname{\pgf@sh@resaveddimen{#1}{#2}}}%
+ \def\pgf@sh@savedmacro#1#2{% MW
+ \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@\pgf@sm@shape@name\endcsname{\pgf@sh@resavedmacro{#1}{#2}}}% MW
+\def\pgf@sh@anchor#1#2{\expandafter\gdef\csname pgf@anchor@\pgf@sm@shape@name @#1\endcsname{#2}}%
+\def\pgf@sh@deferredanchor#1#2{% CJ
+ \expandafter\pgfutil@g@addto@macro
+ \csname pgf@sh@s@\pgf@sm@shape@name\endcsname{\pgf@sh@redeferredanchor{#1}{#2}}}% CJ
+\def\pgf@sh@anchorborder#1{\expandafter\gdef\csname pgf@anchor@\pgf@sm@shape@name @border\endcsname##1{\pgf@process{##1}#1}}%
+\long\def\pgf@sh@behindbgpath#1{\expandafter\gdef\csname pgf@sh@bbg@\pgf@sm@shape@name\endcsname{#1}}%
+\long\def\pgf@sh@bgpath#1{\expandafter\gdef\csname pgf@sh@bg@\pgf@sm@shape@name\endcsname{#1}}%
+\long\def\pgf@sh@beforebgpath#1{\expandafter\gdef\csname pgf@sh@fbg@\pgf@sm@shape@name\endcsname{#1}}%
+\long\def\pgf@sh@behindfgpath#1{\expandafter\gdef\csname pgf@sh@bfg@\pgf@sm@shape@name\endcsname{#1}}%
+\long\def\pgf@sh@fgpath#1{\expandafter\gdef\csname pgf@sh@fg@\pgf@sm@shape@name\endcsname{#1}}%
+\long\def\pgf@sh@beforefgpath#1{\expandafter\gdef\csname pgf@sh@ffg@\pgf@sm@shape@name\endcsname{#1}}%
+\def\pgf@sh@boxes#1{\expandafter\gdef\csname pgf@sh@boxes@\pgf@sm@shape@name\endcsname{#1}}%
+
+\def\pgf@sh@inheritsavedanchors[from=#1]{%
+ \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@\pgf@sm@shape@name\endcsname{\csname pgf@sh@s@#1\endcsname}}%
+
+\def\pgf@sh@inheritanchor[from=#1]#2{%
+ \edef\pgf@marshal{\global\let\expandafter\noexpand\csname
+ pgf@anchor@\pgf@sm@shape@name @#2\endcsname=\expandafter\noexpand\csname
+ pgf@anchor@#1@#2\endcsname}%
+ \pgf@marshal%
+}%
+\def\pgf@sh@inheritanchorborder[from=#1]{%
+ \edef\pgf@marshal{\global\let\expandafter\noexpand\csname
+ pgf@anchor@\pgf@sm@shape@name @border\endcsname=\expandafter\noexpand\csname
+ pgf@anchor@#1@border\endcsname}%
+ \pgf@marshal%
+}%
+\def\pgf@sh@inheritor#1#2{%
+ \edef\pgf@marshal{\global\let\expandafter\noexpand\csname
+ pgf@sh@#1@\pgf@sm@shape@name\endcsname=\expandafter\noexpand\csname
+ pgf@sh@#1@#2\endcsname}%
+ \pgf@marshal%
+}%
+\def\pgf@sh@inheritbehindbgpath[from=#1]{\pgf@sh@inheritor{bbg}{#1}}%
+\def\pgf@sh@inheritbgpath[from=#1]{\pgf@sh@inheritor{bg}{#1}}%
+\def\pgf@sh@inheritbeforebgpath[from=#1]{\pgf@sh@inheritor{fbg}{#1}}%
+\def\pgf@sh@inheritbehindfgpath[from=#1]{\pgf@sh@inheritor{bfg}{#1}}%
+\def\pgf@sh@inheritfgpath[from=#1]{\pgf@sh@inheritor{fg}{#1}}%
+\def\pgf@sh@inheritbeforefgpath[from=#1]{\pgf@sh@inheritor{ffg}{#1}}%
+\def\pgf@sh@inheritboxes[from=#1]{\pgf@sh@inheritor{boxes}{#1}}%
+
+
+
+%
+% Coordinate. This shape is special: It is only used to reference a
+% point for later usage. Nothing is drawn, all anchors are identical
+% to the center.
+%
+
+\pgfdeclareshape{coordinate}
+{%
+ \savedanchor\centerpoint{%
+ % x
+ \pgf@x=.5\wd\pgfnodeparttextbox%
+ % y
+ \pgf@y=.5\ht\pgfnodeparttextbox%
+ \advance\pgf@y by -.5\dp\pgfnodeparttextbox%
+ }%
+
+ \anchor{center}{\centerpoint}%
+ \anchor{north}{\centerpoint}%
+ \anchor{north west}{\centerpoint}%
+ \anchor{north east}{\centerpoint}%
+ \anchor{west}{\centerpoint}%
+ \anchor{east}{\centerpoint}%
+ \anchor{mid}{\centerpoint}%
+ \anchor{mid west}{\centerpoint}%
+ \anchor{mid east}{\centerpoint}%
+ \anchor{base}{\centerpoint}%
+ \anchor{base west}{\centerpoint}%
+ \anchor{base east}{\centerpoint}%
+ \anchor{south}{\centerpoint}%
+ \anchor{south west}{\centerpoint}%
+ \anchor{south east}{\centerpoint}%
+ \anchorborder{\centerpoint}%
+
+ \nodeparts{}% no text
+}%
+
+
+% Value keys for shapes:
+%
+% /pgf/inner xsep : recommended inner x separation
+% /pgf/inner ysep : recommended inner y separation
+% /pgf/outer xsep : recommended outer x separation
+% /pgf/outer ysep : recommended outer y separation
+% /pgf/minimum width : recommended minimum width
+% /pgf/minimum height : recommended minimum height
+
+\pgfset{
+ inner xsep/.initial =.3333em,
+ inner ysep/.initial =.3333em,
+ inner sep/.style ={/pgf/inner xsep={#1},/pgf/inner ysep={#1}},
+ outer xsep/.initial =.5\pgflinewidth,
+ outer ysep/.initial =.5\pgflinewidth,
+ outer sep/.code =\pgf@handle@outer@sep{#1},
+ minimum width/.initial =1pt,
+ minimum height/.initial =1pt,
+ minimum size/.style ={/pgf/minimum width={#1},/pgf/minimum height={#1}},
+}%
+
+
+
+\def\pgf@handle@outer@sep#1{%
+ \def\pgf@temp{#1}%
+ \ifx\pgf@temp\pgf@auto@text%
+ \def\pgf@outer@adjust@hook{%
+ \pgftransformationadjustments%
+ \pgfkeyssetvalue{/pgf/outer xsep}{.5\pgflinewidth*\pgfhorizontaltransformationadjustment}%
+ \pgfkeyssetvalue{/pgf/outer ysep}{.5\pgflinewidth*\pgfverticaltransformationadjustment}%
+ \pgf@outer@auto@adjust@hook%
+ }%
+ \else%
+ \pgfkeyssetvalue{/pgf/outer xsep}{#1}%
+ \pgfkeyssetvalue{/pgf/outer ysep}{#1}%
+ \fi%
+}%
+\def\pgf@auto@text{auto}%
+
+\let\pgf@outer@auto@adjust@hook\relax
+
+
+% Keys for rotating the shape border.
+% (may not be supported by all shapes)
+%
+% /pgf/shape border uses incircle : Calculate the shape border using the incircle
+% around the node contents (+inner sep).
+%
+% /pgf/shape border rotate : Angle of independent border rotation.
+
+\newif\ifpgfshapeborderusesincircle
+\pgfkeys{/pgf/shape border uses incircle/.is if=pgfshapeborderusesincircle}%
+\pgfkeys{/pgf/shape border rotate/.initial=0}%
+
+%
+% Rectangle
+%
+
+\pgfdeclareshape{rectangle}
+{%
+ \savedanchor\northeast{%
+ % Calculate x
+ %
+ % First, is width < minimum width?
+ \pgf@x=\the\wd\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
+ \advance\pgf@x by 2\pgf@xc%
+ \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
+ \ifdim\pgf@x<\pgf@xb%
+ % yes, too small. Enlarge...
+ \pgf@x=\pgf@xb%
+ \fi%
+ % Now, calculate right border: .5\wd\pgfnodeparttextbox + .5 \pgf@x + outer sep
+ \pgf@x=.5\pgf@x%
+ \advance\pgf@x by.5\wd\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
+ \advance\pgf@x by\pgf@xa%
+ % Calculate y
+ %
+ % First, is height+depth < minimum height?
+ \pgf@y=\ht\pgfnodeparttextbox%
+ \advance\pgf@y by\dp\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
+ \advance\pgf@y by 2\pgf@yc%
+ \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}%
+ \ifdim\pgf@y<\pgf@yb%
+ % yes, too small. Enlarge...
+ \pgf@y=\pgf@yb%
+ \fi%
+ % Now, calculate upper border: .5\ht-.5\dp + .5 \pgf@y + outer sep
+ \pgf@y=.5\pgf@y%
+ \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
+ \advance\pgf@y by.5\ht\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
+ \advance\pgf@y by\pgf@ya%
+ }%
+
+ \savedanchor\southwest{%
+ % Calculate x
+ %
+ % First, is width < minimum width?
+ \pgf@x=\wd\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
+ \advance\pgf@x by 2\pgf@xc%
+ \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
+ \ifdim\pgf@x<\pgf@xb%
+ % yes, too small. Enlarge...
+ \pgf@x=\pgf@xb%
+ \fi%
+ % Now, calculate left border: .5\wd\pgfnodeparttextbox - .5 \pgf@x - outer sep
+ \pgf@x=-.5\pgf@x%
+ \advance\pgf@x by.5\wd\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
+ \advance\pgf@x by-\pgf@xa%
+ % Calculate y
+ %
+ % First, is height+depth < minimum height?
+ \pgf@y=\ht\pgfnodeparttextbox%
+ \advance\pgf@y by\dp\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
+ \advance\pgf@y by 2\pgf@yc%
+ \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}%
+ \ifdim\pgf@y<\pgf@yb%
+ % yes, too small. Enlarge...
+ \pgf@y=\pgf@yb%
+ \fi%
+ % Now, calculate upper border: .5\ht-.5\dp - .5 \pgf@y - outer sep
+ \pgf@y=-.5\pgf@y%
+ \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
+ \advance\pgf@y by.5\ht\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
+ \advance\pgf@y by-\pgf@ya%
+ }%
+
+ %
+ % Anchors
+ %
+ \anchor{center}{
+ \pgf@process{\northeast}%
+ \pgf@xa=.5\pgf@x%
+ \pgf@ya=.5\pgf@y%
+ \pgf@process{\southwest}%
+ \pgf@x=.5\pgf@x%
+ \pgf@y=.5\pgf@y%
+ \advance\pgf@x by \pgf@xa%
+ \advance\pgf@y by \pgf@ya%
+ }%
+ \anchor{mid}{\pgf@anchor@rectangle@center\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{base}{\pgf@anchor@rectangle@center\pgf@y=0pt}%
+ \anchor{north}{
+ \pgf@process{\southwest}%
+ \pgf@xa=.5\pgf@x%
+ \pgf@process{\northeast}%
+ \pgf@x=.5\pgf@x%
+ \advance\pgf@x by \pgf@xa%
+ }%
+ \anchor{south}{
+ \pgf@process{\northeast}%
+ \pgf@xa=.5\pgf@x%
+ \pgf@process{\southwest}%
+ \pgf@x=.5\pgf@x%
+ \advance\pgf@x by \pgf@xa%
+ }%
+ \anchor{west}{
+ \pgf@process{\northeast}%
+ \pgf@ya=.5\pgf@y%
+ \pgf@process{\southwest}%
+ \pgf@y=.5\pgf@y%
+ \advance\pgf@y by \pgf@ya%
+ }%
+ \anchor{mid west}{\southwest\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{base west}{\southwest\pgf@y=0pt}%
+ \anchor{north west}{
+ \southwest
+ \pgf@xa=\pgf@x
+ \northeast
+ \pgf@x=\pgf@xa}%
+ \anchor{south west}{\southwest}%
+ \anchor{east}{%
+ \pgf@process{\southwest}%
+ \pgf@ya=.5\pgf@y%
+ \pgf@process{\northeast}%
+ \pgf@y=.5\pgf@y%
+ \advance\pgf@y by \pgf@ya%
+ }%
+ \anchor{mid east}{\northeast\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{base east}{\northeast\pgf@y=0pt}%
+ \anchor{north east}{\northeast}%
+ \anchor{south east}{
+ \northeast
+ \pgf@xa=\pgf@x
+ \southwest
+ \pgf@x=\pgf@xa
+ }%
+ \anchorborder{%
+ \pgf@xb=\pgf@x% xb/yb is target
+ \pgf@yb=\pgf@y%
+ \southwest%
+ \pgf@xa=\pgf@x% xa/ya is se
+ \pgf@ya=\pgf@y%
+ \northeast%
+ \advance\pgf@x by-\pgf@xa%
+ \advance\pgf@y by-\pgf@ya%
+ \pgf@xc=.5\pgf@x% x/y is half width/height
+ \pgf@yc=.5\pgf@y%
+ \advance\pgf@xa by\pgf@xc% xa/ya becomes center
+ \advance\pgf@ya by\pgf@yc%
+ \edef\pgf@marshal{%
+ \noexpand\pgfpointborderrectangle
+ {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
+ {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
+ }%
+ \pgf@process{\pgf@marshal}%
+ \advance\pgf@x by\pgf@xa%
+ \advance\pgf@y by\pgf@ya%
+ }%
+
+ %
+ % Background path
+ %
+ \backgroundpath{
+ \pgfpathrectanglecorners
+ {\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
+ {\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}
+ }%
+}%
+
+
+% Special current path start coordinate:
+\expandafter\def\csname pgf@sh@ns@current subpath start\endcsname{coordinate}%
+\expandafter\def\csname pgf@sh@np@current subpath start\endcsname{%
+ \def\centerpoint{\expandafter\pgfqpoint\pgfsyssoftpath@lastmoveto}%
+}%
+\expandafter\def\csname pgf@sh@nt@current subpath start\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+\expandafter\def\csname pgf@sh@pi@current subpath start\endcsname{\pgfpictureid}%
+
+
+
+% Special current bounding box rectangle:
+\expandafter\def\csname pgf@sh@ns@current bounding box\endcsname{rectangle}%
+\expandafter\def\csname pgf@sh@np@current bounding box\endcsname{%
+ \def\southwest{\pgfqpoint{\pgf@picminx}{\pgf@picminy}}%
+ \def\northeast{\pgfqpoint{\pgf@picmaxx}{\pgf@picmaxy}}%
+}%
+\expandafter\def\csname pgf@sh@nt@current bounding box\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+\expandafter\def\csname pgf@sh@pi@current bounding box\endcsname{\pgfpictureid}%
+
+
+% Special current path bounding box rectangle:
+\expandafter\def\csname pgf@sh@ns@current path bounding box\endcsname{rectangle}%
+\expandafter\def\csname pgf@sh@np@current path bounding box\endcsname{%
+ \def\southwest{\pgfqpoint{\pgf@pathminx}{\pgf@pathminy}}%
+ \def\northeast{\pgfqpoint{\pgf@pathmaxx}{\pgf@pathmaxy}}%
+}%
+\expandafter\def\csname pgf@sh@nt@current path bounding box\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+\expandafter\def\csname pgf@sh@pi@current path bounding box\endcsname{\pgfpictureid}%
+
+
+% Special current page bounding box rectangle:
+\expandafter\def\csname pgf@sh@ns@current page\endcsname{rectangle}%
+\expandafter\def\csname pgf@sh@np@current page\endcsname{%
+ \def\southwest{\pgfpointorigin}%
+ \def\northeast{\pgfpoint{\pgfsys@thepagewidth}{\pgfsys@thepageheight}}%
+}%
+\expandafter\def\csname pgf@sh@nt@current page\endcsname{{1}{0}{0}{1}{0pt}{0pt}}%
+\expandafter\def\csname pgf@sh@pi@current page\endcsname{pgfpageorigin}%
+
+
+% Special scope bounding box rectangle:
+\pgfkeys{/pgf/local bounding box/.code={%
+ \expandafter\gdef\csname pgf@sh@ns@#1\endcsname{rectangle}
+ \expandafter\gdef\csname pgf@sh@np@#1\endcsname{%
+ \def\southwest{\pgfqpoint{\csname pgf@lbb@minx@#1\endcsname}{\csname pgf@lbb@miny@#1\endcsname}}%
+ \def\northeast{\pgfqpoint{\csname pgf@lbb@maxx@#1\endcsname}{\csname pgf@lbb@maxy@#1\endcsname}}%
+ }
+ \expandafter\gdef\csname pgf@sh@nt@#1\endcsname{{1}{0}{0}{1}{0pt}{0pt}}
+ \expandafter\gdef\csname pgf@sh@pi@#1\endcsname{\pgfpictureid}
+ \expandafter\gdef\csname pgf@lbb@maxx@#1\endcsname{-16000pt}%
+ \expandafter\gdef\csname pgf@lbb@minx@#1\endcsname{16000pt}%
+ \expandafter\gdef\csname pgf@lbb@maxy@#1\endcsname{-16000pt}%
+ \expandafter\gdef\csname pgf@lbb@miny@#1\endcsname{16000pt}%
+ \pgf@size@hookedtrue%
+ \expandafter\def\expandafter\pgf@path@size@hook\expandafter{\pgf@path@size@hook\pgf@lbb@do{#1}}
+ },
+ /pgf/freeze local bounding box/.code={%
+ {%
+ \csname pgf@sh@np@#1\endcsname%
+ \southwest%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \northeast%
+ \expandafter\xdef\csname pgf@sh@np@#1\endcsname{%
+ \noexpand\def\noexpand\southwest{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
+ \noexpand\def\noexpand\northeast{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
+ }%
+ }%
+ },
+}%
+\def\pgf@lbb@do#1{%
+ \ifdim\pgf@size@hook@x<\csname pgf@lbb@minx@#1\endcsname\expandafter\xdef\csname pgf@lbb@minx@#1\endcsname{\the\pgf@size@hook@x}\fi%
+ \ifdim\pgf@size@hook@x>\csname pgf@lbb@maxx@#1\endcsname\expandafter\xdef\csname pgf@lbb@maxx@#1\endcsname{\the\pgf@size@hook@x}\fi%
+ \ifdim\pgf@size@hook@y<\csname pgf@lbb@miny@#1\endcsname\expandafter\xdef\csname pgf@lbb@miny@#1\endcsname{\the\pgf@size@hook@y}\fi%
+ \ifdim\pgf@size@hook@y>\csname pgf@lbb@maxy@#1\endcsname\expandafter\xdef\csname pgf@lbb@maxy@#1\endcsname{\the\pgf@size@hook@y}\fi%
+}%
+
+%
+% Circle
+%
+
+\pgfdeclareshape{circle}
+%
+% Draws a circle around the text
+%
+{%
+ \savedanchor\centerpoint{%
+ \pgf@x=.5\wd\pgfnodeparttextbox%
+ \pgf@y=.5\ht\pgfnodeparttextbox%
+ \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
+ }%
+
+ \saveddimen\radius{%
+ %
+ % Calculate ``height radius''
+ %
+ \pgf@ya=.5\ht\pgfnodeparttextbox%
+ \advance\pgf@ya by.5\dp\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
+ \advance\pgf@ya by\pgf@yb%
+ %
+ % Calculate ``width radius''
+ %
+ \pgf@xa=.5\wd\pgfnodeparttextbox%
+ \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
+ \advance\pgf@xa by\pgf@xb%
+ %
+ % Calculate length of radius vector:
+ %
+ \pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
+ \ifdim\pgf@x>\pgf@y%
+ \c@pgf@counta=\pgf@x%
+ \ifnum\c@pgf@counta=0\relax%
+ \else%
+ \divide\c@pgf@counta by 255\relax%
+ \pgf@xa=16\pgf@xa\relax%
+ \divide\pgf@xa by\c@pgf@counta%
+ \pgf@xa=16\pgf@xa\relax%
+ \fi%
+ \else%
+ \c@pgf@counta=\pgf@y%
+ \ifnum\c@pgf@counta=0\relax%
+ \else%
+ \divide\c@pgf@counta by 255\relax%
+ \pgf@ya=16\pgf@ya\relax%
+ \divide\pgf@ya by\c@pgf@counta%
+ \pgf@xa=16\pgf@ya\relax%
+ \fi%
+ \fi%
+ \pgf@x=\pgf@xa%
+ %
+ % If necessary, adjust radius so that the size requirements are
+ % met:
+ %
+ \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%
+ \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%
+ \ifdim\pgf@x<.5\pgf@xb%
+ \pgf@x=.5\pgf@xb%
+ \fi%
+ \ifdim\pgf@x<.5\pgf@yb%
+ \pgf@x=.5\pgf@yb%
+ \fi%
+ %
+ % Now, add larger of outer separations.
+ %
+ \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+ \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+ \ifdim\pgf@xb<\pgf@yb%
+ \advance\pgf@x by\pgf@yb%
+ \else%
+ \advance\pgf@x by\pgf@xb%
+ \fi%
+ }%
+
+ %
+ % Anchors
+ %
+ \anchor{center}{\centerpoint}%
+ \anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{base}{\centerpoint\pgf@y=0pt}%
+ \anchor{north}{\centerpoint\advance\pgf@y by\radius}%
+ \anchor{south}{\centerpoint\advance\pgf@y by-\radius}%
+ \anchor{west}{\centerpoint\advance\pgf@x by-\radius}%
+ \anchor{east}{\centerpoint\advance\pgf@x by\radius}%
+ \anchor{mid west}{\centerpoint\advance\pgf@x by-\radius\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{mid east}{\centerpoint\advance\pgf@x by\radius\pgfmathsetlength\pgf@y{.5ex}}%
+ \anchor{base west}{\centerpoint\advance\pgf@x by-\radius\pgf@y=0pt}%
+ \anchor{base east}{\centerpoint\advance\pgf@x by\radius\pgf@y=0pt}%
+ \anchor{north west}{
+ \centerpoint
+ \pgf@xa=\radius
+ \advance\pgf@x by-0.707107\pgf@xa
+ \advance\pgf@y by0.707107\pgf@xa
+ }%
+ \anchor{south west}{
+ \centerpoint
+ \pgf@xa=\radius
+ \advance\pgf@x by-0.707107\pgf@xa
+ \advance\pgf@y by-0.707107\pgf@xa
+ }%
+ \anchor{north east}{
+ \centerpoint
+ \pgf@xa=\radius
+ \advance\pgf@x by0.707107\pgf@xa
+ \advance\pgf@y by0.707107\pgf@xa
+ }%
+ \anchor{south east}{
+ \centerpoint
+ \pgf@xa=\radius
+ \advance\pgf@x by0.707107\pgf@xa
+ \advance\pgf@y by-0.707107\pgf@xa
+ }%
+ \anchorborder{%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \edef\pgf@marshal{%
+ \noexpand\pgfpointborderellipse
+ {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}
+ {\noexpand\pgfqpoint{\radius}{\radius}}%
+ }%
+ \pgf@marshal%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \centerpoint%
+ \advance\pgf@x by\pgf@xa%
+ \advance\pgf@y by\pgf@ya%
+ }%
+
+ %
+ % Background path
+ %
+ \backgroundpath{%
+ \pgfutil@tempdima=\radius%
+ \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+ \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+ \ifdim\pgf@xb<\pgf@yb%
+ \advance\pgfutil@tempdima by-\pgf@yb%
+ \else%
+ \advance\pgfutil@tempdima by-\pgf@xb%
+ \fi%
+ \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}%
+ }%
+}%
+
+
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmodulesnakes.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmodulesnakes.code.tex
new file mode 100644
index 0000000000..9b692b1340
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmodulesnakes.code.tex
@@ -0,0 +1,369 @@
+% 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{pgfmodulesnakes.code.tex}
+
+\pgfwarning{Snakes have been superseded by decorations. Use the module decorations instead of snakes}
+
+\usepgfmodule{decorations}%
+
+\endinput
+
+
+
+\newdimen\pgfsnakeremainingdistance
+\newdimen\pgfsnakecompleteddistance
+
+
+% Creates a new pgf snake
+%
+% #1 = snake name
+% #1 = initial state
+% #3 = states of the snake
+%
+%
+% This command declares a new snake for later use. The second
+% parameter specifies the states of the snake, see also the
+% description of pgfpathsnake.
+%
+% Inside the code of #3 the command \state may be used. This command
+% will only be defined while #3 is executed.
+%
+% Example:
+%
+% \pgfdeclaresnake{zig zag}{one zig zag}
+% {
+% \state{one zig zag}[width=10pt]
+% {
+% \pgfpathlineto{\pgfpoint{2.5pt}{2.5pt}}
+% \pgfpathlineto{\pgfpoint{7.5pt}{-2.5pt}}
+% \pgfpathlineto{\pgfpoint{10pt}{0pt}}
+% }
+% \state{final}
+% {
+% \pgfpathlineto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}}
+% }
+% }
+
+\long\def\pgfdeclaresnake#1#2#3{%
+ \def\pgf@snake@name{#1}%
+ \pgfutil@namedef{pgf@snake@@#1@initial}{#2}%
+ \let\pgf@orig@state=\state%
+ \let\state=\pgf@snake@state
+ #3
+ \let\state=\pgf@orig@state%
+}%
+
+
+% Sets the additional transformation applied to every segment of a snake
+%
+% #1 = transformation
+%
+% Example:
+%
+% \pgfsetsnakesegmenttransformation{\pgftransformyshift{5pt}}
+
+\def\pgfsetsnakesegmenttransformation#1{\def\pgf@snakeadditionaltransform{#1}}%
+\pgfsetsnakesegmenttransformation{}%
+
+
+% Declares a new state
+%
+% #1 = state name
+% #2 = options
+% #3 = path element
+%
+% Description:
+%
+% When a snake is drawn and the current state is #1, the following
+% happens. First, the options are executed, which will possible change
+% the state. If that does not happen, the path element is added to the
+% path and the coordinate system is translated by the path element's
+% width (which is specified using the width option).
+%
+% Example:
+%
+% \state{initial}[width=10pt]
+% {
+% \pgfpathlineto{\pgfpoint{2.5pt}{2.5pt}}
+% \pgfpathlineto{\pgfpoint{7.5pt}{-2.5pt}}
+% \pgfpathlineto{\pgfpoint{10pt}{0pt}}
+% }
+
+\def\pgf@snake@state#1{\pgfutil@ifnextchar[{\pgf@@snake@start#1}{\pgf@@snake@start#1[]}}%}%
+\def\pgf@@snake@start#1[#2]#3{%
+ \pgfutil@namedef{pgf@snake@@\pgf@snake@name @#1@options}{#2}%
+ \pgfutil@namedef{pgf@snake@@\pgf@snake@name @#1@code}{#3}%
+}%
+
+
+
+% Use multiple snakes
+%
+% #1 = list of snake names/length pairs
+% #2 = point to which the snake leads
+%
+% This operation uses the snakes in parameter #1 to get to the point
+% #4. The parameter #1 should contain pairs consisting of a snake name
+% and a length for which this snake should be used. When the length is
+% computed, the dimensions \pgfsnakeremainingdistance and
+% \pgfsnakecompleteddistance will have been set to the length of the
+% total distance to #2 that has already been covered/that still needs
+% to be covered.
+%
+% Example:
+%
+% \pgfpathsnakesto{{lineto}{1cm},{zig zag}{\pgfsnakeremainingdistance}}{\pgfpoint{2cm}{3cm}}
+
+\def\pgfpathsnakesto#1#2{%
+ \begingroup%
+ % compute target vector
+ \pgfpointtransformed{#2}%
+ \advance\pgf@x by-\pgf@path@lastx%
+ \advance\pgf@y by-\pgf@path@lasty%
+ %
+ % MW: Calculate the angle of the snake.
+ %
+ \edef\pgf@marshal{%
+ \noexpand\pgfmathanglebetweenpoints{\noexpand\pgfpointorigin}{%
+ \noexpand\pgf@x\the\pgf@x\noexpand\pgf@y\the\pgf@y}%
+ }%
+ \pgf@marshal%
+ \let\pgfsnakeangle\pgfmathresult%
+ %
+ % MW: Use this instead for length (?). More accurate and only a few operations slower.
+ %
+ \pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}%
+ \pgfsnakeremainingdistance\pgfmathresult pt\relax%
+ %
+ % Ok, now normalize the vector...
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{\pgfpointnormalised{}}%
+ % ok, now computer length (arghh...)
+ % In theory that's easy: divide the larger of the values x or y by
+ % the normalized x or y. Well...
+ %
+ % First, make xa and ya positive:
+ % \ifdim\pgf@xa<0pt%
+% \pgf@xa=-\pgf@xa%
+% \fi%
+% \ifdim\pgf@ya<0pt%
+% \pgf@ya=-\pgf@ya%
+% \fi%
+% % Now do division:
+% \ifdim\pgf@xa>\pgf@ya%
+% \c@pgf@counta=\pgf@x%
+% \ifnum\c@pgf@counta=0\relax%
+% \else%
+% \divide\c@pgf@counta by 255\relax%
+% \pgf@xa=16\pgf@xa\relax%
+% \divide\pgf@xa by\c@pgf@counta%
+% \pgf@xa=16\pgf@xa\relax%
+% \fi%
+% \else%
+% \c@pgf@counta=\pgf@y%
+% \ifnum\c@pgf@counta=0\relax%
+% \else%
+% \divide\c@pgf@counta by 255\relax%
+% \pgf@ya=16\pgf@ya\relax%
+% \divide\pgf@ya by\c@pgf@counta%
+% \pgf@xa=16\pgf@ya\relax%
+% \fi%
+% \fi%
+% % Make positive:
+% \ifdim\pgf@xa<0pt%
+% \pgf@xa=-\pgf@xa%
+% \fi%
+% % Ok, now we draw things...
+ \edef\pgf@list{#1}%
+% \pgfsnakeremainingdistance=\pgf@xa%
+ \pgfsnakecompleteddistance=0pt%
+ \pgf@xb=\pgf@x%
+ \pgf@yb=\pgf@y%
+ \pgfutil@for\pgf@temp:=\pgf@list\do{%
+ \ifx\pgf@temp\pgfutil@empty%
+ \else%
+ \expandafter\pgf@snake@invoke\pgf@temp%
+ \fi%
+ }%
+ \endgroup%
+}%
+
+\def\pgf@snake@invoke#1#2{%
+ \pgfmathsetlength\pgf@xa{#2}%
+ {%
+ \edef\pgf@marshal{\noexpand\pgfpathsnakealongvector{#1}{\the\pgf@xa}{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}}%
+ \pgf@marshal%
+ }%
+ \advance\pgfsnakecompleteddistance by\pgf@xa%
+ \advance\pgfsnakeremainingdistance by-\pgf@xa%
+}%
+
+% Use a snake
+%
+% #1 = snake name
+% #2 = point to which the snake leads
+%
+% This operation mainly computes \pgfpathsnakealongvector for a vector
+% appropriately chosen. See \pgfpathsnakealongvector for details.
+%
+% Example:
+%
+% \pgfpathsnaketo{zig zag}{\pgfpoint{2cm}{3cm}}
+
+\def\pgfpathsnaketo#1#2{\pgfpathsnakesto{{#1}{\pgfsnakeremainingdistance}}{#2}}%
+
+
+
+% Use a snake
+%
+% #1 = snake name
+% #2 = length of the snake
+% #3 = vector along which the snake grows, should have unit length.
+%
+% This command draws a snake (more precisely, it adds a snake to the
+% path). This works as follows:
+%
+% First, the coordinate system is transformed such that the vector #3
+% points to the right.
+%
+% Next, the state `initial' of the snake is entered. Unless the
+% options of this state cause it to switch to another state, the path
+% element is added to the path. Then, the coordinate system is
+% translated by the width of the path element as specified in the
+% width option of the path element. The dimensions
+% \pgfsnakeremainingdistance and \pgfsnakecompleteddistance are
+% updated.
+%
+% The process ends when the state `final' is entered. The code of the
+% final state is executed and the process stops.
+%
+% Example:
+%
+% \pgfpathsnakealongvector{zig zag}{100pt}{\pgfpolar{30}{1pt}}
+
+\def\pgfpathsnakealongvector#1#2#3{%
+ \pgfutil@ifundefined{pgf@snake@@#1@initial}{\pgferror{Undefined snake ``#1''}}
+ {
+ \begingroup% keep things local
+ \pgftransformreset%
+ \pgf@pt@x=\pgf@path@lastx% evil trickery to transform to the last point
+ \pgf@pt@y=\pgf@path@lasty%
+ \pgf@process{#3}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@xb=-\pgf@y%
+ \pgf@yb=\pgf@x%
+ \pgftransformcm
+ {\pgf@sys@tonumber{\pgf@xa}}{\pgf@sys@tonumber{\pgf@ya}}
+ {\pgf@sys@tonumber{\pgf@xb}}{\pgf@sys@tonumber{\pgf@yb}}
+ {\pgfpointorigin}%
+ % Now, setup the automaton
+ \expandafter\let\expandafter\pgf@snake@current@state\expandafter=\csname pgf@snake@@#1@initial\endcsname%
+ \def\pgf@snake@name{#1}%
+ \pgfsnakecompleteddistance=0pt%
+ \pgfmathsetlength\pgfsnakeremainingdistance{#2}%
+ \pgf@snake@run%
+ % Last step:
+ {%
+ \pgftransformxshift{\pgfsnakecompleteddistance}%
+ \pgf@snakeadditionaltransform%
+ \csname pgf@snake@@#1@final@code\endcsname%
+ }%
+ \endgroup%
+ }%
+}%
+
+\def\pgf@final@text{final}%
+
+\def\pgf@snake@run{%
+ \let\pgf@snake@next=\pgf@snake@do@state%
+ \ifx\pgf@snake@current@state\pgf@final@text%
+ \let\pgf@snake@next=\relax%
+ \fi%
+ \pgf@snake@next%
+}%
+
+\def\pgf@snake@do@state{%
+ \let\pgf@snake@next=\relax%
+ \let\pgf@snake@next@state=\pgf@snake@current@state%
+ % execute options
+ \expandafter\expandafter\expandafter\pgf@snakes@setter
+ \expandafter\expandafter\expandafter{\csname pgf@snake@@\pgf@snake@name @\pgf@snake@current@state @options\endcsname}%
+ \ifx\pgf@snake@next\relax%
+ \let\pgf@snake@next=\pgf@snake@do@code%
+ \fi%
+ \pgf@snake@next%
+}%
+\def\pgf@snakes@setter{%
+ \pgfqkeys{/pgf/snakes}%
+}%
+
+\def\pgf@snake@do@code{%
+ % Ok, execute code:
+ {%
+ \pgftransformxshift{\pgfsnakecompleteddistance}%
+ \pgf@snakeadditionaltransform%
+ \csname pgf@snake@@\pgf@snake@name @\pgf@snake@current@state @code\endcsname%
+ }%
+ % next, do transformation and update
+ \pgfmathsetlength{\pgf@xa}{\pgf@snake@width}%
+ \advance\pgfsnakeremainingdistance by-\pgf@xa%
+ \advance\pgfsnakecompleteddistance by\pgf@xa%
+ % Next iteration:
+ \let\pgf@snake@current@state=\pgf@snake@next@state%
+ \pgf@snake@run%
+}%
+
+\pgfkeys{
+ /pgf/snakes/width/.code=\def\pgf@snake@width{#1}\pgf@snake@switch@if#1 to final\pgf@stop,%
+ /pgf/snakes/switch if less than/.code=\pgf@snake@switch@if#1\pgf@stop,%
+ /pgf/snakes/next state/.store in=\pgf@snake@next@state%
+}%
+
+\def\pgf@snake@switch@if#1to #2\pgf@stop{%
+ \ifx\pgf@snake@next\relax%
+ \pgfmathsetlength\pgf@x{#1}%
+ \ifdim\pgfsnakeremainingdistance<\pgf@x%
+ \def\pgf@snake@current@state{#2}%
+ \let\pgf@snake@next=\pgf@snake@run%
+ \fi%
+ \fi%
+}%
+
+
+
+% lineto snake
+%
+% This snake simply adds a straight line. This snake is mainly useful
+% in conjunction with other snakes.
+
+\pgfdeclaresnake{lineto}{final}
+{%
+ \state{final}
+ { \pgfpathlineto{\pgfqpoint{\pgfsnakeremainingdistance}{0pt}} }
+}%
+
+
+
+% moveto snake
+%
+% This snake simply jumps to the end. This snake, too, is mainly
+% useful in conjunction with other snakes.
+
+\pgfdeclaresnake{moveto}{final}
+{%
+ \state{final}
+ { \pgfpathmoveto{\pgfqpoint{\pgfsnakeremainingdistance}{0pt}} }
+}%
+
+
+
+\endinput
diff --git a/graphics/pgf/base/tex/generic/modules/pgfmodulesorting.code.tex b/graphics/pgf/base/tex/generic/modules/pgfmodulesorting.code.tex
new file mode 100644
index 0000000000..9aa1df9fef
--- /dev/null
+++ b/graphics/pgf/base/tex/generic/modules/pgfmodulesorting.code.tex
@@ -0,0 +1,69 @@
+% 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{pgfmodulesorting.code.tex}
+
+%
+% This file defines commands for sorting data. This is useful for 3d plots,
+% but also for drawing things in the correct order.
+%
+
+
+\newcount\pgfsortingbuckets
+
+
+% Init the sorting
+%
+% #1 = number of buckets
+%
+% Description:
+%
+% This macro inits a sorting. At any time there can be only one active
+% sorting. When you init the sorting, #1 should be a number of
+% buckets. You can then call \pgfsortinginsert to insert code into the
+% buckets. Once you are done, calling \pgfsortingexecute will execute
+% first the code in buckets 0, then the code in bucket 1, and so on to
+% bucket number #1-1.
+%
+\def\pgfsortinginit#1{
+ \pgfsortingbuckets#1\relax%
+ \c@pgf@counta=0\relax
+ \pgfutil@loop
+ \ifnum\c@pgf@counta<\c@pgf@countb\relax%
+ \expandafter\global\expandafter\let\csname pgf@sort@\the\c@pgf@counta\endcsname\pgfutil@empty%
+ \advance\c@pgf@counta by1\relax%
+ \pgfutil@repeat
+}%
+
+% Insert code into some bucket
+%
+% #1 = the bucket
+% #2 = the code
+%
+\def\pgfsortinginsert#1#2{
+ \expandafter\let\expandafter\pgf@temp\csname pgf@lib@sort@#1\endcsname%
+ \expandafter\def\expandafter\pgf@temp\expandafter{\pgf@temp#2}%
+ \expandafter\global\expandafter\let\csname pgf@lib@sort@\the\c@pgf@counta\endcsname\pgf@temp%
+}%
+
+
+% After all code has been inserted into the buckets, you can call
+% this method to execute the code in the order of the buckets.
+\def\pgfsortingexecute{
+ \c@pgf@countb=\pgfoovalueof{buckets}\relax
+ \c@pgf@counta=0\relax
+ \pgfutil@loop
+ \ifnum\c@pgf@counta<\c@pgf@countb\relax%
+ \csname pgf@lib@sort@\the\c@pgf@counta\endcsname%
+ \advance\c@pgf@counta by1\relax%
+ \pgfutil@repeat
+}%
+
+
+\endinput