% 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
