% Copyright 2006 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.

\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorearrows.code.tex,v 1.11 2008/04/23 14:59:01 tantau Exp $


% Sets the end arrow
%
% #1 = An arrow name
%
% Example:
%
% \pgfsetarrowsend{stealth}

\def\pgfsetarrowsend#1{\pgf@arrowset{end}{#1}}
\def\pgf@arrowset#1#2{%
  \pgfutil@ifundefined{pgf@arrow@code@#2}
  {\PackageError{pgf}{Arrow #1 type ``#2'' unknown}{}}
  {%
    \edef\pgf@arrow@temp{#2}%
    \ifx\pgf@arrow@temp\pgfutil@empty% ah. clear!
      \expandafter\let\csname pgf@#1arrow\endcsname=\pgfutil@empty%
      \expandafter\let\csname pgf@shorten@#1\endcsname=\pgfutil@empty%
    \else%
      %\pgf@arrow@prepare{#2}%
      \expandafter\def\csname pgf@#1arrow\endcsname{\pgf@arrow@call{#2}}%
      \expandafter\edef\csname pgf@shorten@#1\endcsname{\expandafter\noexpand\csname pgf@arrow@right@#2\endcsname}%
    \fi%
  }%
}


% Sets the start arrow
%
% #1 = An arrow name
%
% Example:
%
% \pgfsetarrowsstart{stealth}

\def\pgfsetarrowsstart#1{\pgf@arrowset{start}{\csname pgf@arrows@invert#1\endcsname}}

\def\pgf@arrows@invname#1#2{\expandafter\def\csname pgf@arrows@invert#1\endcsname{#2}}
\pgf@arrows@invname{}{}




% Sets arrows
%
% #1 = An arrow specification of the form ``left''-``right''. The last
%      and right should be arrow types that have been defined using
%      the \pgfarrowsdef command
%
% Example:
%
% \pgfsetarrows{-to}

\def\pgfsetarrows#1{\pgf@arrows#1\pgf@stop}
\def\pgf@arrows#1-#2\pgf@stop{%
  \pgfsetarrowsstart{#1}
  \pgfsetarrowsend{#2}
}

\def\pgf@arrows@checked#1#2#3{%
  \pgfutil@ifundefined{pgf@arrow@code@#2}%
  {%
    \PackageError{pgf}{Arrow end type ``#2'' unknown}{}}%
  {%
    \pgfutil@ifundefined{pgf@arrow@code@\csname pgf@arrows@invert#1\endcsname}
    {\PackageError{pgf}{Arrow start type ``#1'' unknown}{}}%
    {#3}%
  }%
}

\def\pgf@arrows@check@already#1#2#3{%
  \pgfutil@ifundefined{pgf@arrow@code@#2}
  {#3}%
  {\PackageError{pgf}{Arrow end type ``#2'' already defined}{}}%
}


% Called when an arrow needs to be rendered

\def\pgf@arrow@call#1{%
  \expandafter\ifx\csname\pgf@arrow@full@name{#1}\endcsname\relax%
    \pgfsysprotocol@getcurrentprotocol\pgf@arrow@temp%
    {%
      \pgfinterruptpath%
        \let\pgfusepath=\pgf@nousepath@here%
        \pgf@relevantforpicturesizefalse%
        \pgftransformreset%
        \pgfsysprotocol@setcurrentprotocol\pgfutil@empty%
        \pgfsysprotocol@bufferedtrue%
        \pgfsys@beginscope%
        \csname pgf@arrow@code@#1\endcsname%
        \pgfsys@endscope%
        \pgfsysprotocol@getcurrentprotocol\pgf@@arrow@temp%
        \global\let\pgf@@arrow@temp=\pgf@@arrow@temp%
      \endpgfinterruptpath%
      \expandafter\def\expandafter\pgf@temp\expandafter{\expandafter\pgfsys@invoke\expandafter{\pgf@@arrow@temp}}%
      \expandafter\global\expandafter\let\csname\pgf@arrow@full@name{#1}\endcsname=\pgf@temp%
    }%
    \pgfsysprotocol@setcurrentprotocol\pgf@arrow@temp%
  \fi%
  \csname\pgf@arrow@full@name{#1}\endcsname%
} 

\def\pgf@arrow@full@name#1{pgf@arrow@prot@#1@\the\pgflinewidth @\pgfinnerlinewidth @\pgfgetarrowoptions{#1}}

\def\pgf@arrow@code@{} % dummy

\def\pgf@nousepath@here#1{%
  \PackageError{pgf}{The definition of an arrow may not use \string\pgfusepath}{}
}


% Get options for an arrow
%
% #1 = arrow tip name
%
% Description:
%
% For every arrow tip certain options can be set, which may influence
% the appearance of the arrow tip. How the options are used is up the
% arrow tip code. This command will expand to the current value of
% the options for this tip. The default is 0. 

\def\pgfgetarrowoptions#1{%
  \expandafter\ifx\csname pgf@arrow@opt@#1\endcsname\relax0\else\csname pgf@arrow@opt@#1\endcsname\fi%
}


% Set options for an arrow
%
% #1 = arrow tip name
% #2 = options
%
% Description:
%
% Sets the arrow tip options for an arrow. The options should be a
% normal string and will be used to detect whether an arrow should be
% recached. For instance, when you set the arrow tip options of
% "myarrow" to "1", the arrow will be rendered in a certain way. Then,
% when you set the options to "2", the arrow will be rerendered.

\def\pgfsetarrowoptions#1#2{%
  \expandafter\def\csname pgf@arrow@opt@#1\endcsname{#2}%
}




% Define an arrow type.
%
% #1 = name or mnemonic for arrow when used at the start (examples: ``to'' or ``<'')
% #2 = name or mnemonic for arrow when used at the end (examples: ``to'' or ``>'')
% #3 = code to setup the left and right extend of the arrow. To set
%      the left extend, call \pgfarrowsleftextend, for the right \pgfarrowsrightextend.
% #4 = protocolable code
%
% Description:
%
% When you define an arrow using this command, you must give two
% names. The first is used for the arrow when it is ``at the start'',
% the other when it is at the end. For example, a simple arrow might
% have the names ``<'' and ``>'', though these particular names are
% not used by pgf and left for the user.
%
% The code should be ``protocolable'' code. This means that it uses
% only pretty simple commands. 
%
% The arrow code will be protocolled once for each line width at which
% the arrow is used. Thus, the code can (and often should) depend on
% the line width.
%
% The arrow should ``point right'' in the coordinate system. The end
% of the line at which the arrow should be drawn will be at the origin
% of the coordinate system. The coordinate system will be scaled and
% rotated appropriately before the arrow is drawn.
%
% The right extend of the arrow should be set to how much the arrow
% ``protrudes over the right''. Prior to drawing the arrow, the line
% will be shortened by this amount so that the arrow tip will exactly
% touch the original right end of the unshortened line.
%
% The left extend specifies the leftmost point of the arrow. This is
% important only if you use the swapping command, when this end is
% used to compute the shortening. 
%
% The definition of an arrow should normally take care of the fact
% that the line cap of the main line may be a butt cap, a round cap or
% a rect cap. In all cases, the arrow should ``cover'' the cap
% completely or not at all.
%
% Example:
%
% \pgfarrowsdeclare{stealth}{stealth}
% {
%   \pgfarrowsleftextend{-6\pgflinewidth}
%   \pgfarrowsrightextend{2\pgflinewidth}
% {
%   \pgfpathmoveto{\pgfpoint{2\pgflinewidth}{0pt}}
%   \pgfpathlineto{\pgfpoint{-6\pgflinewidth}{4\pgflinewidth}}
%   \pgfpathlineto{\pgfpoint{-3\pgflinewidth}{0pt}}
%   \pgfpathlineto{\pgfpoint{-6\pgflinewidth}{-4\pgflinewidth}}
%   \pgfusepathqfill
% }

\def\pgfarrowsdeclare#1#2#3#4{%
  \pgf@arrows@check@already{#1}{#2}
  {%
    \expandafter\def\csname pgf@arrow@code@#2\endcsname{#4}%
    \expandafter\def\csname pgf@arrow@left@#2\endcsname{#3\advance\pgf@x by-\pgf@xa}%
    \expandafter\def\csname pgf@arrow@right@#2\endcsname{#3\advance\pgf@x by\pgf@xb}%
    \pgf@arrows@invname{#1}{#2}%
  }%
}

\def\pgfarrowsleftextend#1{\pgfmathsetlength\pgf@xa{#1}}
\def\pgfarrowsrightextend#1{\pgfmathsetlength\pgf@xb{#1}}

\def\pgf@arrows@repeat#1#2{%
  \edef\pgf@arrows@marshal{\noexpand\let\expandafter\noexpand\csname#2\endcsname=\expandafter\noexpand\csname#1\endcsname}%
  \pgf@arrows@marshal}



% Declare a new arrow type to be the same as another one.
%
% #1 = name of new start
% #2 = name or new end
% #3 = name or old start
% #4 = name or old end
%
% Example:
%
% \pgfarrowsdeclarealias{<}{>}{to}{to}

\def\pgfarrowsdeclarealias#1#2#3#4{%
  \pgf@arrows@check@already{#1}{#2}
  {%
    \pgf@arrows@checked{#3}{#4}%
    {%
      \pgf@arrows@repeat{pgf@arrow@code@#4}{pgf@arrow@code@#2}%
      \pgf@arrows@repeat{pgf@arrow@left@#4}{pgf@arrow@left@#2}%
      \pgf@arrows@repeat{pgf@arrow@right@#4}{pgf@arrow@right@#2}%
      \pgf@arrows@invname{#1}{#2}%
    }%
  }%
}




% Creates a new arrows by ``swapping'' an existing arrow.
%
% #1 = name of new start
% #2 = name of new end
% #3 = name of old start
% #4 = name of old end
%
% Example:
%
% \pgfarrowsdeclarealias{]}{[}{[}{]}

\def\pgfarrowsdeclarereversed#1#2#3#4{%
  \pgf@arrows@check@already{#1}{#2}%
  {%
    \pgf@arrows@checked{#3}{#4}%
    {%
      \expandafter\def\csname pgf@arrow@code@#2\endcsname{%
        \pgflowlevel{\pgftransformxscale{-1}}%
        \csname pgf@arrow@code@#4\endcsname}%
      \pgf@arrows@repeat{pgf@arrow@right@#4}{pgf@arrow@left@#2}%
      \pgf@arrows@repeat{pgf@arrow@left@#4}{pgf@arrow@right@#2}%
      \pgf@arrows@invname{#1}{#2}%
    }%
  }%
}



% Creates new arrows by combining two existing arrows.
%
% #1 = optional additional space
% #2 = name of new start
% #3 = name of new end
% #4 = name of second (innermost) start
% #5 = name of second end
% #6 = name of first (outermost) start
% #7 = name of first end
%
% In the star form, the line will end at the innermost arrows,
% otherwise the line will end at the outermost arrows.
%
% Example:
%
% \pgfarrowsdeclarecombine*{|<}{>|}{|}{|}{<}{>}
% \pgfarrowsdeclarecombine{<<}{>>}{<}{>}{<}{>}

\def\pgfarrowsdeclarecombine{\pgfutil@ifnextchar*{\pgfarrowsdeclarecombine@star}{\pgf@@arrowsdeclarecombine}}

\def\pgf@@arrowsdeclarecombine{\pgfutil@ifnextchar[{\pgf@arrowsdeclarecombine}{\pgf@arrowsdeclarecombine[0pt]}}
\def\pgf@arrowsdeclarecombine[#1]#2#3#4#5#6#7{%
  \pgf@arrows@check@already{#2}{#3}%
  {%
    \pgf@arrows@checked{#4}{#5}%
    {%
      \pgf@arrows@checked{#6}{#7}%
      {%
        \expandafter\edef\csname pgf@arrow@code@#3\endcsname{%
          \noexpand\pgfscope%
          {\expandafter\noexpand\csname pgf@arrow@code@#7\endcsname}%
          \noexpand\endpgfscope%
          {%
            \noexpand\pgfmathsetlength\pgf@x{#1}%
            \noexpand\pgf@process{\expandafter\noexpand\csname pgf@arrow@left@#7\endcsname}%
            \noexpand\pgf@process{\expandafter\noexpand\csname pgf@arrow@right@#5\endcsname}%
            \pgf@x=-\pgf@x%
            \noexpand\pgflowlevel{\noexpand\pgftransformxshift{\pgf@x}}%
            \expandafter\noexpand\csname pgf@arrow@code@#5\endcsname}%
          }%
        \pgf@arrows@repeat{pgf@arrow@right@#7}{pgf@arrow@right@#3}%
        \expandafter\def\csname pgf@arrow@left@#3\endcsname{%
          \pgf@process{%
            \pgfmathsetlength\pgf@y{#1}%
            \advance\pgf@x by\pgf@y%
            \pgf@process{\csname pgf@arrow@left@#7\endcsname}%
            \pgf@process{\csname pgf@arrow@right@#5\endcsname}%
            \pgf@process{\csname pgf@arrow@left@#5\endcsname}%
          }%
        }%
        \pgf@arrows@invname{#2}{#3}%
      }%
    }%
  }%
}

\def\pgfarrowsdeclarecombine@star*{\pgfutil@ifnextchar[{\pgf@arrowsdeclarecombine@star}{\pgf@arrowsdeclarecombine@star[0pt]}}
\def\pgf@arrowsdeclarecombine@star[#1]#2#3#4#5#6#7{%
  \pgf@arrows@check@already{#2}{#3}%
  {%
    \pgf@arrows@checked{#4}{#5}%
    {%
      \pgf@arrows@checked{#6}{#7}%
      {%
        \expandafter\edef\csname pgf@arrow@code@#3\endcsname{%
          \noexpand\pgfscope%
            {%
              \noexpand\pgfmathsetlength\pgf@x{#1}%
              \pgf@process{\expandafter\noexpand\csname pgf@arrow@left@#7\endcsname}%
              \pgf@process{\expandafter\noexpand\csname pgf@arrow@right@#5\endcsname}%
              \noexpand\pgflowlevel{\noexpand\pgftransformxshift{\pgf@x}}%
            }%
            {\expandafter\noexpand\csname pgf@arrow@code@#7\endcsname}%
          \noexpand\endpgfscope%
          \expandafter\noexpand\csname pgf@arrow@code@#5\endcsname%
        }%
        \pgf@arrows@repeat{pgf@arrow@left@#7}{pgf@arrow@left@#3}%
        \expandafter\def\csname pgf@arrow@right@#3\endcsname{%
          \pgf@process{%
            \pgfmathsetlength\pgf@y{#1}%
            \advance\pgf@x by\pgf@y%
            \pgf@process{\csname pgf@arrow@left@#7\endcsname}%
            \pgf@process{\csname pgf@arrow@right@#5\endcsname}%
            \pgf@process{\csname pgf@arrow@right@#7\endcsname}%
          }%
        }%
        \pgf@arrows@invname{#2}{#3}%
      }%
    }%
  }%
}



% Creates new arrows by doubling/tripling existing arrows.
%
% #1 = optional additional space in multiples of line width
% #2 = name of new start
% #3 = name of new end
% #4 = name of old start
% #5 = name of old end
%
% Example:
%
% \pgfarrowsdeclaredouble{<<}{>>}{<}{>}

\def\pgfarrowsdeclaredouble{\pgfutil@ifnextchar[{\pgf@arrowsdeclaredouble}{\pgf@arrowsdeclaredouble[0pt]}}
\def\pgf@arrowsdeclaredouble[#1]#2#3#4#5{\pgfarrowsdeclarecombine[#1]{#2}{#3}{#4}{#5}{#4}{#5}}
\def\pgfarrowsdeclaretriple{\pgfutil@ifnextchar[{\pgf@arrowsdeclaretriple}{\pgf@arrowsdeclaretriple[0pt]}}
\def\pgf@arrowsdeclaretriple[#1]#2#3#4#5{%
  \pgfarrowsdeclarecombine[#1]{pgf@trip@#2}{pgf@trip@#3}{#4}{#5}{#4}{#5}%
  \pgfarrowsdeclarecombine[#1]{#2}{#3}{pgf@trip@#2}{pgf@trip@#3}{#4}{#5}%
}


% A stealth-fighter-like pointed arrow
%
% Example:
%
% \pgfsetarrows{-stealth}

\pgfarrowsdeclare{stealth}{stealth}
{
  \pgfutil@tempdima=0.28pt%
  \pgfutil@tempdimb=\pgflinewidth%
  \ifdim\pgfinnerlinewidth>0pt%
    \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
  \fi%
  \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
  \pgfarrowsleftextend{+-3\pgfutil@tempdima}
  \pgfarrowsrightextend{+5\pgfutil@tempdima}
}
{
  \pgfutil@tempdima=0.28pt%
  \pgfutil@tempdimb=\pgflinewidth%
  \ifdim\pgfinnerlinewidth>0pt%
    \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
  \fi%
  \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
  \pgfpathmoveto{\pgfqpoint{5\pgfutil@tempdima}{0pt}}
  \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}}
  \pgfpathlineto{\pgfpointorigin}
  \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}}
  \pgfusepathqfill
}

\pgfarrowsdeclarereversed{stealth reversed}{stealth reversed}{stealth}{stealth}


% An arrow similar to the $\to$ arrow
%
% Example:
%
% \pgfsetarrow{-to}

\pgfarrowsdeclare{to}{to}
{
  \pgfutil@tempdima=-0.84pt%
  \advance\pgfutil@tempdima by-1.3\pgflinewidth%
  \pgfutil@tempdimb=0.21pt%
  \advance\pgfutil@tempdimb by.625\pgflinewidth%
  \pgfarrowsleftextend{+\pgfutil@tempdima}
  \pgfarrowsrightextend{+\pgfutil@tempdimb}
}
{
  \pgfutil@tempdima=0.28pt%
  \advance\pgfutil@tempdima by.3\pgflinewidth%
  \pgfsetlinewidth{0.8\pgflinewidth}
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-2.75\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{0pt}{0.25\pgfutil@tempdima}}
  {\pgfqpoint{0.75\pgfutil@tempdima}{0pt}}
  \pgfpathcurveto
  {\pgfqpoint{0pt}{-0.25\pgfutil@tempdima}}
  {\pgfqpoint{-2.75\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{to reversed}{to reversed}
{
  \pgfutil@tempdima=-0.21pt%
  \advance\pgfutil@tempdima by-0.475\pgflinewidth%
  \pgfutil@tempdimb=0.98pt%
  \advance\pgfutil@tempdimb by1.45\pgflinewidth%
  \pgfarrowsleftextend{+\pgfutil@tempdima}
  \pgfarrowsrightextend{+\pgfutil@tempdimb}
}
{
  \pgfutil@tempdima=0.28pt%
  \advance\pgfutil@tempdima by.3\pgflinewidth%
  \pgfsetlinewidth{+0.8\pgflinewidth}
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{3.5\pgfutil@tempdima}{4\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{3.25\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{0.5\pgfutil@tempdima}{0.25\pgfutil@tempdima}}
  {\pgfqpoint{-0.25\pgfutil@tempdima}{0\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{0.5\pgfutil@tempdima}{-0.25\pgfutil@tempdima}}
  {\pgfqpoint{3.25\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{3.5\pgfutil@tempdima}{-4\pgfutil@tempdima}}
  \pgfusepathqstroke
}



% LaTeX's orginal arrow type
%
% Example:
%
% \pgfsetarrows{-latex}

\pgfarrowsdeclare{latex}{latex}
{
  \pgfutil@tempdima=0.28pt%
  \pgfutil@tempdimb=\pgflinewidth%
  \ifdim\pgfinnerlinewidth>0pt%
    \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
  \fi%
  \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
  \pgfarrowsleftextend{+-1\pgfutil@tempdima}
  \pgfarrowsrightextend{+9\pgfutil@tempdima}
}
{
  \pgfutil@tempdima=0.28pt%
  \pgfutil@tempdimb=\pgflinewidth%
  \ifdim\pgfinnerlinewidth>0pt%
    \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
  \fi%
  \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
  \pgfpathmoveto{\pgfqpoint{9\pgfutil@tempdima}{0pt}}
  \pgfpathcurveto
  {\pgfqpoint{6.3333\pgfutil@tempdima}{.5\pgfutil@tempdima}}
  {\pgfqpoint{2\pgfutil@tempdima}{2\pgfutil@tempdima}}
  {\pgfqpoint{-1\pgfutil@tempdima}{3.75\pgfutil@tempdima}}
  \pgfpathlineto{\pgfqpoint{-1\pgfutil@tempdima}{-3.75\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{2\pgfutil@tempdima}{-2\pgfutil@tempdima}}
  {\pgfqpoint{6.3333\pgfutil@tempdima}{-.5\pgfutil@tempdima}}
  {\pgfqpoint{9\pgfutil@tempdima}{0pt}}
  \pgfusepathqfill
}
\pgfarrowsdeclarereversed{latex reversed}{latex reversed}{latex}{latex}



% A bar shaped arrow
%
% Example:
%
% \pgfsetarrows{-|}

\pgfarrowsdeclare{|}{|}
{
  \pgfarrowsleftextend{+-0.25\pgflinewidth}
  \pgfarrowsrightextend{+.75\pgflinewidth}
}
{
  \pgfutil@tempdima=2pt%
  \advance\pgfutil@tempdima by1.5\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetrectcap
  \pgfpathmoveto{\pgfqpoint{0.25\pgflinewidth}{-\pgfutil@tempdima}}
  \pgfpathlineto{\pgfqpoint{0.25\pgflinewidth}{\pgfutil@tempdima}}
  \pgfusepathqstroke
}


% A space arrow
%
% This arrow can be combined with other arrows to add "space" around
% them. 
%
% Example:
%
% \pgfarrowsdeclarecombine{my<}{my>}{<}{>}{space}{space}

\pgfarrowsdeclare{space}{space}
{
  \pgfutil@tempdima=0.88pt%
  \advance\pgfutil@tempdima by.3\pgflinewidth%
  \pgfarrowsleftextend{0pt}
  \pgfarrowsrightextend{\pgfutil@tempdima}
}
{}



\endinput
