Current File : //usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex |
% 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