% 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/pgfcorepathusage.code.tex,v 1.12 2008/04/22 17:03:26 tantau Exp $


% Stroke/fill/clip/etc. the current path. Depending on the options,
% the current path will be stroked/filled/clipped/etc. If no options
% are given, the path is stroked. If multiple options are given, all
% of them are performed (in a sensible order).
%
% #1 = action(s) to be applied to the current path. Valid actions are: 
%      stroke -  strokes the path. If no options are given, this is the
%                default. 
%      draw -    same as stroke.
%      fill -    fills the path.
%      clip -    clip the path.
%      discard - Discards the path. Same effect as having an empty
%                options list.
%
% Example:
%
% % Draws an edge.
% \pgfpathmoveto{\pgfxy(0,0)}
% \pgfpathlineto{\pgfxy(0,1)}
% \pgfpathlineto{\pgfxy(1,0)}
% \pgfusepath{stroke}

\pgfkeys{
  /pgf/stroke/.code=\def\pgf@up@stroke{stroke},
  /pgf/draw/.code=\def\pgf@up@stroke{stroke},
  /pgf/fill/.code=\def\pgf@up@fill{fill},
  /pgf/clip/.code=\def\pgf@up@clip{clip},
  /pgf/discard/.code=,
  /pgf/use as bounding box/.code=\def\pgf@up@bb{\pgf@relevantforpicturesizefalse}
}

\def\pgfusepath#1{%
  \let\pgf@up@stroke\pgfutil@empty%
  \let\pgf@up@fill\pgfutil@empty%
  \let\pgf@up@clip\pgfutil@empty%
  \let\pgf@up@discard\pgfutil@empty%
  \let\pgf@up@bb\pgfutil@empty%
  \pgfset{#1}%
  \expandafter\def\expandafter\pgf@up@action\expandafter{\csname pgfsys@\pgf@up@fill\pgf@up@stroke\endcsname}%
  \ifx\pgf@up@stroke\pgfutil@empty%
    \ifx\pgf@up@fill\pgfutil@empty%
      \ifx\pgf@up@clip\pgfutil@empty%
        \let\pgf@up@action=\pgfutil@empty%
        \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
      \else%
        % only clipping  
        \let\pgf@up@action=\pgfsys@discardpath%
      \fi%
    \fi%
  \fi%  
  \pgfsyssoftpath@getcurrentpath\pgf@last@processed@path
  \pgfprocessround{\pgf@last@processed@path}{\pgf@last@processed@path}% change the path
  \pgfsyssoftpath@setcurrentpath\pgf@last@processed@path%
  %
  % Check whether the path is stroked. If so, add half the line width
  % to the bounding box.
  %
  \ifpgf@relevantforpicturesize%
    \ifx\pgf@up@stroke\pgfutil@empty%
    \else%
      \ifdim\pgf@picmaxx=-16000pt\relax%
      \else%
        \pgf@x=\pgf@pathminx\advance\pgf@x by-.5\pgflinewidth%
        \ifdim\pgf@x<\pgf@picminx\global\pgf@picminx\pgf@x\fi%
        \pgf@y=\pgf@pathminy\advance\pgf@y by-.5\pgflinewidth%
        \ifdim\pgf@y<\pgf@picminy\global\pgf@picminy\pgf@y\fi%
        \pgf@x=\pgf@pathmaxx\advance\pgf@x by.5\pgflinewidth%
        \ifdim\pgf@x>\pgf@picmaxx\global\pgf@picmaxx\pgf@x\fi%
        \pgf@y=\pgf@pathmaxy\advance\pgf@y by.5\pgflinewidth%
        \ifdim\pgf@y>\pgf@picmaxy\global\pgf@picmaxy\pgf@y\fi%
      \fi%
    \fi%
  \fi%
  %
  \ifx\pgf@up@clip\pgfutil@empty%
    \ifx\pgf@up@stroke\pgfutil@empty%
      \pgfsyssoftpath@invokecurrentpath%
      \pgfsyssoftpath@getcurrentpath\pgf@last@used@path%
      \pgf@up@action%
    \else%
      \pgf@check@for@arrows%
      \ifpgf@drawarrows%
        \pgf@shorten@path@as@needed%
        \pgfsyssoftpath@invokecurrentpath%
        \pgfsyssoftpath@getcurrentpath\pgf@last@used@path%
        \pgf@up@action%
        \pgf@stroke@inner@line@if@needed%
        \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
        \pgf@add@arrows@as@needed%
      \else%
        \pgfsyssoftpath@invokecurrentpath%
        \pgfsyssoftpath@getcurrentpath\pgf@last@used@path%
        \pgf@up@action%
        \pgf@stroke@inner@line@if@needed%
      \fi%
    \fi%
  \else%
    \pgfsyssoftpath@invokecurrentpath%
    \pgfsyssoftpath@getcurrentpath\pgf@last@used@path%
    \pgfsys@clipnext%
    \pgf@up@action%
    \pgf@relevantforpicturesizefalse%
  \fi%
  \pgf@up@bb%
  \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
  \pgf@resetpathsizes%
  \ignorespaces%
}

\def\pgf@stroke@inner@line@if@needed{%
  \ifdim\pgfinnerlinewidth>0pt\relax%
    \pgfsys@beginscope%
    {%
      \pgfsys@setlinewidth{\pgfinnerlinewidth}%
      \pgfsetstrokecolor{\pgfinnerstrokecolor}%
      \pgfsyssoftpath@invokecurrentpath%
      \pgfsys@stroke%
    }%
    \pgfsys@endscope%
  \fi%
}

% Shorten start/end of paths by a certain amount.
%
% #1 = amount by which paths should be shortened.
%
% Example:
%
% \pgfpathmoveto{\pgfpointorigin}
% \pgfpathlineto{\pgfpoint{10pt}{0pt}
%
% % The following has the same effect:
% \pgfsetshortenstart{1pt}
% \pgfpathmoveto{\pgfpointorigin}
% \pgfpathlineto{\pgfpoint{11pt}{0pt}

\def\pgfsetshortenstart#1{\pgfmathsetlength\pgf@shorten@start@additional{#1}}
\def\pgfsetshortenend#1{\pgfmathsetlength\pgf@shorten@end@additional{#1}}

\newif\ifpgf@drawarrows

\def\pgf@check@for@arrows{%
  \pgf@drawarrowsfalse%
  \ifx\pgf@startarrow\pgfutil@empty\else\pgf@drawarrowstrue\fi%
  \ifx\pgf@endarrow\pgfutil@empty\else\pgf@drawarrowstrue\fi%
  \ifdim\pgf@shorten@end@additional=0pt\relax\else\pgf@drawarrowstrue\fi%
  \ifdim\pgf@shorten@start@additional=0pt\relax\else\pgf@drawarrowstrue\fi%
  \ifpgf@drawarrows%
    \pgfsyssoftpath@getcurrentpath\pgf@arrowpath%
    \ifx\pgf@arrowpath\pgfutil@empty%
      \pgf@drawarrowsfalse%
    \else%
      \pgfprocesscheckclosed{\pgf@arrowpath}{\pgf@drawarrowsfalse}%
    \fi%
  \fi%
}

\newdimen\pgf@shorten@end@additional
\newdimen\pgf@shorten@start@additional

\let\pgf@shorten@end=\pgfutil@empty
\let\pgf@shorten@start=\pgfutil@empty

\def\pgf@shorten@path@as@needed{%
  \pgfprocesspathextractpoints{\pgf@arrowpath}%
  \let\pgf@arrow@next=\pgf@shorten@now%
  \ifx\pgf@shorten@start\pgfutil@empty%
    \ifx\pgf@shorten@end\pgfutil@empty%
      \ifdim\pgf@shorten@end@additional=0pt\relax%
        \ifdim\pgf@shorten@start@additional=0pt\relax%
          \let\pgf@arrow@next=\relax%
        \fi%
      \fi%
    \fi%
  \fi%
  \pgf@arrow@next%
}

\def\pgf@shorten@now{%
  {%
    \pgf@x=0pt%
    \pgf@shorten@start%
    \advance\pgf@x by\pgf@shorten@start@additional%
    \pgf@xc=\pgf@x%
    \pgfpointlineatdistance{\pgf@xc}{\pgfpointfirstonpath}{\pgfpointsecondonpath}%
    \global\pgf@xb=\pgf@x%
    \global\pgf@yb=\pgf@y%
    \pgf@process{\pgfpointsecondonpath}%
    \global\advance\pgf@x by\pgf@xa%
    \global\advance\pgf@y by\pgf@ya%
  }%
  \edef\pgfpointfirstonpath{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
  \edef\pgfpointsecondonpath{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
  {%
    \pgf@x=0pt%
    \pgf@shorten@end%
    \advance\pgf@x by\pgf@shorten@end@additional%
    \pgf@xc=\pgf@x%
    \pgfpointlineatdistance{\pgf@xc}{\pgfpointlastonpath}{\pgfpointsecondlastonpath}%
    \global\pgf@xb=\pgf@x%
    \global\pgf@yb=\pgf@y%
    \pgf@process{\pgfpointsecondlastonpath}%
    \global\advance\pgf@x by\pgf@xa%
    \global\advance\pgf@y by\pgf@ya%
  }%
  \edef\pgfpointlastonpath{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
  \edef\pgfpointsecondlastonpath{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
  \pgfprocesspathreplacestartandend{\pgf@arrowpath}{\pgfpointfirstonpath}{\pgfpointlastonpath}%
  \pgfsyssoftpath@setcurrentpath\pgf@arrowpath%
}

\def\pgf@add@arrows@as@needed{%
  \ifx\pgf@startarrow\pgfutil@empty%
  \else%
    \pgflowlevelobj%
      {\pgftransformarrow{\pgfpointsecondonpath}{\pgfpointfirstonpath}}
      {\pgf@startarrow}%
  \fi%
  \ifx\pgf@endarrow\pgfutil@empty%
  \else%
    \pgflowlevelobj%
      {\pgftransformarrow{\pgfpointsecondlastonpath}{\pgfpointlastonpath}}
      {\pgf@endarrow}%
  \fi%      
}

\let\pgf@startarrow=\pgfutil@empty
\let\pgf@endarrow=\pgfutil@empty

\endinput
