% Copyright 2024 by Qrrbrbirlbel
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Free Documentation License.
%

\unless\ifcsname tikzextset\endcsname
  \input tikzext-util.tex
\fi


% \tikzext@arrow@evalshift
%
% Stores the shift amount into \tikzext@arrow@shift@
%
\def\tikzext@arrow@evalshift#1#2#3{%
  \pgf@arrow@compute@shortening#1%
  \ifcase\pgfkeysvalueof{/tikz/ext/arrow/shift mode}\relax
    \def#3{0pt}%
  \or
    \pgfmathsetlengthmacro#3%
      {(\pgfkeysvalueof{/tikz/ext/arrow shift factor #2})*-\pgf@xb}%
  \or
    \pgfmathsetlengthmacro#3%
      {(\pgfkeysvalueof{/tikz/ext/arrow shift factor #2})*-\pgf@xa}%
  \fi
}


% For bended arrows the shifting can't simply be done by a transformation
\def\tikzext@arrow@sneak#1\pgf@stop#2#3{% TODO
  \unless\ifdim#3=0pt
    \def#2{#1\pgf@arrow@handle{_}{\pgfarrowsep=#3\relax}}%
  \fi
}

%
% Arrow keys
%
\pgfkeysdef{/tikz/ext/pos > angle}{%
  \pgfkeysvalueof{/tikz/pos/.@cmd}(#1-\tikz@timer@start@angle)/(\tikz@timer@end@angle-\tikz@timer@start@angle)\pgfeov}
\tikzextset{%
  every softpath arrows/.code=
    \pgfkeysdef{/tikz/pos >}{\pgfkeysvalueof{/tikz/pos/.@cmd}##1\pgfeov}%
    \pgfkeysdef{/tikz/pos <}{\pgfkeyssetvalue{/tikz/ext/pos <}{##1}},
  every arc arrows/.code=
    \pgfkeysdef{/tikz/pos > angle}{\pgfkeysvalueof{/tikz/ext/pos > angle/.@cmd}##1\pgfeov}%
    \pgfkeysdef{/tikz/pos < angle}{\pgfkeysvalueof{/tikz/ext/pos < angle/.@cmd}##1\pgfeov}%
    \pgfkeysdef{/tikz/pos >}{\pgfkeysvalueof{/tikz/pos/.@cmd}##1\pgfeov}%
    \pgfkeysdef{/tikz/pos <}{\pgfkeyssetvalue{/tikz/ext/pos <}{##1}},
  pos < angle/.code=\pgfkeyssetvalue{/tikz/ext/pos <}{(#1-\tikz@timer@start@angle)/(\tikz@timer@end@angle-\tikz@timer@start@angle)},
  softpath arrows/.default=,
  softpath arrows/.code={%
    \begingroup
      \tikzset{ext/every softpath arrows,#1}%
      \pgfsyssoftpath@getcurrentpath\tikz@temp
      \pgfprocesssplitsubpath\tikz@temp
      \expandafter\pgf@parse@end\pgfprocessresultsubpathsuffix\pgf@stop\pgf@stop\pgf@stop
      \tikzext@arrow@softpath@curve
      \setbox\tikz@whichbox=\hbox\bgroup
        \unhbox\tikz@whichbox
        \hbox\bgroup\bgroup
          \pgfinterruptpath
          \pgfscope
            \pgfutil@ifxempty\pgf@start@tip@sequence{}{%
              \tikzext@arrow@evalshift\pgf@start@tip@sequence{start}\tikzext@arrow@shift@start
              \expandafter\tikzext@arrow@sneak\pgf@start@tip@sequence\pgf@stop\pgf@start@tip@sequence\tikzext@arrow@shift@start
            }%
            \pgfutil@ifxempty\pgf@end@tip@sequence{}{%
              \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
              \expandafter\tikzext@arrow@sneak\pgf@end@tip@sequence\pgf@stop\pgf@end@tip@sequence\tikzext@arrow@shift@end
            }%
            \pgfset{tips}%
            \pgftransformreset
            \tikzext@arrow@softpath
            \pgfusepath{}%
          \endpgfscope
          \endpgfinterruptpath
        \egroup\egroup
      \egroup
    \global\setbox\tikz@tempbox=\box\tikz@whichbox%
    \expandafter\endgroup%
    \expandafter\setbox\tikz@whichbox=\box\tikz@tempbox%
  },
  arc arrows/.default=,
  arc arrows/.code={%
    \ifx\tikz@timer\tikz@timer@arc
      \begingroup
        \tikzset{ext/every arc arrows,#1}%
        \setbox\tikz@whichbox=\hbox\bgroup
          \unhbox\tikz@whichbox
          \hbox\bgroup\bgroup
            \pgfinterruptpath
            \pgfscope
              \pgfutil@ifxempty\pgf@start@tip@sequence{}{%
                \tikzext@arrow@evalshift\pgf@start@tip@sequence{start}\tikzext@arrow@shift@start
                \expandafter\tikzext@arrow@sneak\pgf@start@tip@sequence\pgf@stop\pgf@start@tip@sequence\tikzext@arrow@shift@start
              }%
              \pgfutil@ifxempty\pgf@end@tip@sequence{}{%
                \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
                \expandafter\tikzext@arrow@sneak\pgf@end@tip@sequence\pgf@stop\pgf@end@tip@sequence\tikzext@arrow@shift@end
              }%
              \pgfset{tips}%
              \tikzext@arrow@arcpath
              \pgfusepath{}%
            \endpgfscope
            \endpgfinterruptpath
          \egroup\egroup
        \egroup
      \global\setbox\tikz@tempbox=\box\tikz@whichbox
      \expandafter\endgroup
      \expandafter\setbox\tikz@whichbox=\box\tikz@tempbox
    \else
      \pgfutil@packagewarning{tikz-ext}
        {arc arrow used on non-arc path segment, using ``softpath arrows'' instead}%
      \tikzset{ext/softpath arrows={#1}}%
    \fi
  },
  pos </.initial=0.0,
  pos >/.style={/tikz/pos={#1}},
  arrow shift mode/.is choice,
  arrow shift mode/off/.code                  =\pgfkeyssetvalue{/tikz/ext/arrow/shift mode}{0},
  arrow shift mode/total length/.code         =\pgfkeyssetvalue{/tikz/ext/arrow/shift mode}{1},
  arrow shift mode/total/.code                =\pgfkeyssetvalue{/tikz/ext/arrow/shift mode}{1},
  arrow shift mode/length until line end/.code=\pgfkeyssetvalue{/tikz/ext/arrow/shift mode}{2},
  arrow shift mode/line end/.code             =\pgfkeyssetvalue{/tikz/ext/arrow/shift mode}{2},
  arrow shift mode=total length,
  arrow shift factor/.code=\pgfkeyssetvalue{/tikz/ext/arrow shift factor start}{#1}%
                           \pgfkeyssetvalue{/tikz/ext/arrow shift factor end}{#1},
  arrow shift factor start/.initial=.5,
  arrow shift factor end/.initial=.5
}
%
% Arrow pics
%
\tikzset{
  pics/ext/arrow/.default=,
  pics/ext/arrow/.style={
    /tikz/sloped, /tikz/allow upside down,
    foreground code=, background code=, setup code=,
    code=%
      \edef\tikzext@temp{#1}%
      \pgfutil@ifxempty\tikzext@temp{}{%
        \pgfsetarrowsend{#1}%
      }%
      \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
      \pgftransformxshift{+-\tikzext@arrow@shift@end}%
      \pgf@arrow@draw@arrow\pgf@end@tip@sequence\pgf@xb
  },
  pics/ext/softpath arrow/.default=,
  pics/ext/softpath arrow/.code={%
    \let\pgf@start@tip@sequence\pgfutil@empty
    \edef\tikzext@temp{#1}%
    \pgfutil@ifxempty\tikzext@temp{}{%
      \pgfsetarrowsend{#1}%
    }%
    \pgfqkeys{/tikz/pics}{ext/softpath arrows}%
  },
  pics/ext/softpath arrows/.default=,
  pics/ext/softpath arrows/.style={
    foreground code=, background code=,
    setup code={%
      \edef\tikzext@temp{#1}%
      \pgfutil@ifxempty\tikzext@temp{}{%
        \pgfsetarrows{#1}%
      }%
      \pgfutil@ifxempty\pgf@start@tip@sequence{}{%
        \tikzext@arrow@evalshift\pgf@start@tip@sequence{start}\tikzext@arrow@shift@start
        \expandafter\tikzext@arrow@sneak\pgf@start@tip@sequence\pgf@stop\pgf@start@tip@sequence\tikzext@arrow@shift@start
      }%
      \pgfutil@ifxempty\pgf@end@tip@sequence{}{%
        \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
        \expandafter\tikzext@arrow@sneak\pgf@end@tip@sequence\pgf@stop\pgf@end@tip@sequence\tikzext@arrow@shift@end
      }%
      \pgfsyssoftpath@getcurrentpath\tikz@temp
      \pgfprocesssplitsubpath\tikz@temp
      \expandafter\pgf@parse@end\pgfprocessresultsubpathsuffix\pgf@stop\pgf@stop\pgf@stop
      \tikzext@arrow@softpath@curve
    },
    code=%
      \pgfset{tips}%
      \pgftransformreset
      \tikzext@arrow@softpath
      \pgfusepath{}%
  }
}

% curve
\def\tikzext@arrow@softpath@curve{%
  \ifx\pgfpointthirdlastonpath\relax
    \let\tikzext@arrow@softpath\tikzext@arrow@linepath
  \else
    \let\tikzext@arrow@softpath\tikzext@arrow@curvepath
  \fi
}
%
% Paths
%
% Line
\def\tikzext@arrow@linepath{%
  \pgfpathmoveto{%
    \pgfpointlineattime
      {\pgfkeysvalueof{/tikz/ext/pos <}}
      {\pgfpointsecondlastonpath}
      {\pgfpointlastonpath}%
  }%
  \pgfpathlineto{%
    \pgfpointlineattime
      {\tikz@time}
      {\pgfpointsecondlastonpath}
      {\pgfpointlastonpath}%
  }%
}
% Curve
\def\tikzext@arrow@curvepath{%
  \pgfpathcurvebetweentime
    {\pgfkeysvalueof{/tikz/ext/pos <}}
    {\tikz@time}
    {\pgfpointfourthlastonpath}
    {\pgfpointthirdlastonpath}
    {\pgfpointsecondlastonpath}
    {\pgfpointlastonpath}%
}

\def\tikzext@arrow@arcpath{%
  \pgfmathcos@{\tikz@timer@start@angle}%
  \let\tikz@angle@cos\pgfmathresult
  \pgfmathsin@{\tikz@timer@start@angle}%
  \let\tikz@angle@sin\pgfmathresult
  \pgfpathmoveto{%
    \pgfpointarcaxesattime
      {\pgfkeysvalueof{/tikz/ext/pos <}}
      {\pgfpointdiff{%
          \pgfpointadd{\pgfpointscale{\tikz@angle@cos}{\tikz@timer@zero@axis}}
                      {\pgfpointscale{\tikz@angle@sin}{\tikz@timer@ninety@axis}}}{\tikz@timer@start}}
      {\tikz@timer@zero@axis}
      {\tikz@timer@ninety@axis}
      {\tikz@timer@start@angle}
      {\tikz@timer@end@angle}%
  }%
  \pgfpatharcaxes
    {(\tikz@timer@end@angle-\tikz@timer@start@angle)*%
      (\pgfkeysvalueof{/tikz/ext/pos <})+\tikz@timer@start@angle}
    {(\tikz@timer@end@angle-\tikz@timer@start@angle)*%
      (\tikz@time)+\tikz@timer@start@angle}
    {\tikz@timer@zero@axis}
    {\tikz@timer@ninety@axis}%
}
%
% \arrow(reversed)*(*) macro for decoration.markings
%
\def\pgf@lib@dec@doarrowhead{%
  \pgfutil@ifnextchar*%
    {\tikzext@lib@dec@doarrowhead{1}}
    {\pgfutil@ifnextchar[%
      {\tikz@lib@dec@doarrowhead}
      {\tikz@lib@dec@doarrowhead[]}%
    }%
}
\def\pgf@lib@dec@doarrowheadrev{%
  \pgfutil@ifnextchar*%
    {\tikzext@lib@dec@doarrowhead{-1}}
    {\pgfutil@ifnextchar[%
      {\tikz@lib@dec@doarrowheadrev}
      {\tikz@lib@dec@doarrowheadrev[]}%
    }%
}

\def\tikzext@lib@dec@doarrowhead#1*{%
  \pgfutil@ifnextchar*%
    {\tikzext@lib@dec@doarrowhead@@{#1}}
    {\pgfutil@ifnextchar[%
      {\tikzext@lib@dec@doarrowhead@{#1}}
      {\tikzext@lib@dec@doarrowhead@{#1}[]}}%
}
\def\tikzext@lib@dec@doarrowhead@#1[#2]#3{%
  \scope[{#2}]%
    \pgfsetarrowsend{#3}%
    \pgfutil@ifxempty\pgf@end@tip@sequence{}{%
      \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
      \pgftransformxscale{#1}%
      \pgftransformxshift{+-\tikzext@arrow@shift@end}%
      \pgf@arrow@draw@arrow\pgf@end@tip@sequence\pgf@xb
    }%
  \endscope
}
\def\tikzext@lib@dec@doarrowhead@@#1*{%
  \pgfutil@ifnextchar[%]
    {\tikzext@lib@dec@doarrowhead@@@{#1}}
    {\tikzext@lib@dec@doarrowhead@@@{#1}[]}%
}

\def\tikzext@lib@dec@doarrowhead@@@#1[#2]#3{%
  \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto
    \pgftransformreset
    \pgfset{tips}%
    \ifnum#1<0
      \pgfsetarrows{[reversed]}%
    \fi
    \scope[{#2}]%
      \pgfsetarrowsend{#3}%
      \pgfutil@ifxempty\pgf@end@tip@sequence{}{%
        \tikzext@arrow@evalshift\pgf@end@tip@sequence{end}\tikzext@arrow@shift@end
        \expandafter\tikzext@arrow@sneak\pgf@end@tip@sequence\pgf@stop\pgf@end@tip@sequence\tikzext@arrow@shift@end
        \ifdim\pgf@decorate@inputsegmenttime pt=1pt % something weird for 1.0
          \def\pgf@decorate@inputsegmenttime{1}%
        \fi
        \ifdim\pgf@decorate@inputsegmenttime pt<0.05pt % zero is bad
          \def\pgf@decorate@inputsegmenttime{0.05}%
        \fi
        \pgfpathcurvebetweentime{0}{\pgf@decorate@inputsegmenttime}%
            {\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}%
            {\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}%
        \pgfusepath{}%
      }%
    \endscope
  \else
    \tikzext@lib@dec@doarrowhead@{#1}[{#2}]{#3}%
  \fi
}
\endinput