%--------------------------------------------
%
% Package pgfplots
%
% Provides a user-friendly interface to create function plots (normal
% plots, semi-logplots and double-logplots).
% 
% It is based on Till Tantau's PGF package.
%
% Copyright 2007/2008 by Christian Feuersänger.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
% 
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
% 
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.
%
%--------------------------------------------

%
% This file contains the implementation for stacked plots.
%
% Stacked plots always keep record of the last plotted coordinates.
% Any new plot will be ADDED on top of the last plotted coordinates.
% 
% Terminology: "last plotted coordinates" are called "zero levels"
% because they actually work like shifts.
%
% Programming Structure:
%
% 1. We keep TWO lists of coordinates: a list of CURRENT zero level
% coordinates and a list of NEXT zero level coordinates.
%
% The first one will be queried whenever a zero level coordinate is
% requested.
%
% The second one will be used to form zero levels for the next plot.
%
% 2. At the beginning and end of each plot, the lists in 1.) are
% initialised properly.
%
% 3. While plot coordinates are processed, the following methods
% interact with the stacked API:
% \pgfplots@stacked@preparepoint@inmacro
% 	-> compute the 'stacked' sum.
% 	This may need to be done with floating point arithmetics because
% 	the data scaling trafo is not yet initialised
%
% \pgfplots@stacked@finishpoint
% 	-> takes coordinates as they will be given to Tikz. This method is
% 	used to 
% 		- communicate zero level coordinates to Tikz
% 		- implement the 'closed paths' option (allows filled stacked plots).
%
% \pgfplots@stacked@rememberzerolevelpoint@for@next@plot
% \pgfplots@stacked@getnextzerolevelpoint
%
% 4. Zero levels are communicated to Tikz by
% \pgfplots@stacked@initzerolevelhandler. This routine initialises an
% input stream for Tikz plot handlers which produces a sequence of
% zero levels. It is used by [xy]comb and [xy]bar.
%
%
% REMARK:
% the state of the boolean \ifpgfplots@datascaletrafo@initialised
% determines whether these routines expect and return floating point
% numbers or fixed point numbers.

\let\pgfplots@stacked@zerolevelpoint@x=\pgfutil@empty
\let\pgfplots@stacked@zerolevelpoint@y=\pgfutil@empty
\newif\ifpgfplots@stacked@isfirstplot
\newif\ifpgfplots@stacked@isinitialised

% Pre-initialisation.
% Needs to be called before the first call to
% \pgfplots@stacked@beginplot.
\def\pgfplots@stacked@initialise{%
	\pgfplots@stacked@isfirstplottrue
	\pgfplots@stacked@isinitialisedtrue
}%

% Cleanup method. Truncates any global variables to reduce string
% space.
\def\pgfplots@stacked@finalize{%
	\global\pgfplotslistnewempty\pgfplots@stacked@zerolevellist
	\global\pgfplotslistnewempty\pgfplots@stacked@nextzerolevellist
	\pgfplots@stacked@isinitialisedfalse
}%

% (Re)defines the macro \pgfplots@stacked@getnextzerolevelpoint
% at the beginning of each plot.
%
% The macro \pgfplots@stacked@getnextzerolevelpoint fills
% \pgfplots@stacked@zerolevelpoint@[xy].
%
% ATTENTION: call \pgfplots@stacked@initialise before the first call
% to beginplot!
\def\pgfplots@stacked@beginplot{%
%\message{pgfplots@stacked@beginplot: PLOT STARTED.}%
	\ifpgfplots@stacked@isinitialised
	\else
		\pgfplots@error{LOGIC ERROR: please call \string\pgfplots@stacked@initialise.}%
	\fi
	\global\pgfplotslistnewempty\pgfplots@stacked@PGFzerolevels
	% accumulate this command here for \closedcycle:
	\let\pgfplots@stacked@closedcycle@impl=\pgfutil@empty
	\ifpgfplots@stacked@isfirstplot
		\global\pgfplotslistnewempty\pgfplots@stacked@zerolevellist
		\def\pgfplots@stacked@zerolevelpoint@x{0}%
		\def\pgfplots@stacked@zerolevelpoint@y{0}%
		% only work with float if its really necessary - for
		% example if the scaling trafo which maps to pgfmath is
		% not yet initialised.
		\ifpgfplots@datascaletrafo@initialised
		\else
			\ifpgfplots@xislinear
				\pgfmathfloatcreate{0}{0.0}{0}%
				\let\pgfplots@stacked@zerolevelpoint@x=\pgfmathresult
			\fi
			\ifpgfplots@yislinear
				\pgfmathfloatcreate{0}{0.0}{0}%
				\let\pgfplots@stacked@zerolevelpoint@y=\pgfmathresult
			\fi
		\fi
		\def\pgfplots@stacked@getnextzerolevelpoint{}% will remain constant anyway.
	\else
		{\globaldefs=1
		\pgfplotslistcopy\pgfplots@stacked@nextzerolevellist\to\pgfplots@stacked@zerolevellist
		}%
		\def\pgfplots@stacked@getnextzerolevelpoint{%
			{\globaldefs=1
			\pgfplotslistpopfront\pgfplots@stacked@zerolevellist\to\pgfmathresult
			}%
			\expandafter\pgfplots@stacked@parsezerolevelpoint\pgfmathresult
		}%
	\fi
	\global\pgfplotslistnewempty\pgfplots@stacked@nextzerolevellist
}%

\def\pgfplots@stacked@parsezerolevelpoint(#1,#2){%
	\def\pgfplots@stacked@zerolevelpoint@x{#1}%
	\def\pgfplots@stacked@zerolevelpoint@y{#2}%
}

\def\pgfplots@stacked@endplot{%
	\ifpgfplots@stacked@isfirstplot
		\let\pgfplots@stacked@closedcycle@impl=\pgfplots@path@closed@cycle@std
	\else
		\t@pgfplots@tokc=\expandafter{\pgfplots@stacked@closedcycle@impl}%
		\edef\pgfplots@stacked@closedcycle@impl{%
			[mark=none,/utils/exec=\noexpand\pgfplots@try@mirror@plot@handler]
			--plot coordinates{\the\t@pgfplots@tokc}
			--cycle
		}%
	\fi
	\global\pgfplots@stacked@isfirstplotfalse
%\message{pgfplots@stacked@endplot: PLOT ENDED}%
}%

% WARNING: when this method is called, NEITHER
% \ifpgfplots@stacked@isfirstplot NOR the zero level lists are
% initialised!
\def\pgfplots@stacked@initzerolevelhandler{%
	\ifpgfplots@stacked@x
		\pgfplotxzerolevelstream@@list
		\pgfplotyzerolevelstreamconstant{\pgfplots@ZERO@y}%
	\else
		\pgfplotxzerolevelstreamconstant{\pgfplots@ZERO@x}%
		\pgfplotyzerolevelstream@@list
	\fi
}%

\def\pgfplots@stacked@rememberzerolevelpoint@for@next@plot#1{%
	\edef\pgfplots@loc@TMPa{#1}%
	\expandafter\pgfplotslistpushbackglobal\pgfplots@loc@TMPa\to\pgfplots@stacked@nextzerolevellist
}

\def\pgfplots@stacked@finishpoint#1#2{%
	\ifpgfplots@stacked@isfirstplot
	\else
		\pgfpointxy{\pgfplots@stacked@zerolevelpoint@x}{\pgfplots@stacked@zerolevelpoint@y}%
		\ifpgfplots@stacked@x
			\edef\pgfplots@loc@TMPa{\the\pgf@x}%
		\else
			\edef\pgfplots@loc@TMPa{\the\pgf@y}%
		\fi
		\expandafter\pgfplotslistpushbackglobal\pgfplots@loc@TMPa\to\pgfplots@stacked@PGFzerolevels
		\t@pgfplots@toka=\expandafter{\pgfplots@stacked@closedcycle@impl}%
		\edef\pgfplots@stacked@closedcycle@impl{%
			(\pgfplots@stacked@zerolevelpoint@x,\pgfplots@stacked@zerolevelpoint@y)%
			\the\t@pgfplots@toka}%
	\fi
}%

\def\pgfplots@stacked@preparepoint@inmacro#1#2{%
	\pgfplots@stacked@getnextzerolevelpoint
	\ifpgfplots@stacked@x
		\ifpgfplots@stacked@plus
			\let\pgfplots@stacked@op=\pgfmathadd@
		\else
			\let\pgfplots@stacked@op=\pgfmathsubtract@
		\fi
		\ifpgfplots@xislinear
			\ifpgfplots@datascaletrafo@initialised
			\else
				\ifpgfplots@stacked@plus
					\let\pgfplots@stacked@op=\pgfmathfloatadd@
				\else
					\let\pgfplots@stacked@op=\pgfmathfloatsubtract@
				\fi
			\fi
		\fi
		\pgfplots@stacked@op{\pgfplots@stacked@zerolevelpoint@x}{#1}%
		\let#1=\pgfmathresult
	\else
		\ifpgfplots@stacked@plus
			\let\pgfplots@stacked@op=\pgfmathadd@
		\else
			\let\pgfplots@stacked@op=\pgfmathsubtract@
		\fi
		\ifpgfplots@yislinear
			\ifpgfplots@datascaletrafo@initialised
			\else
				\ifpgfplots@stacked@plus
					\let\pgfplots@stacked@op=\pgfmathfloatadd@
				\else
					\let\pgfplots@stacked@op=\pgfmathfloatsubtract@
				\fi
			\fi
		\fi
		\pgfplots@stacked@op{\pgfplots@stacked@zerolevelpoint@y}{#2}%
		\let#2=\pgfmathresult
	\fi
	\pgfplots@stacked@rememberzerolevelpoint@for@next@plot{(#1,#2)}%
}

% This here is a re-implementation of the stored plot processing.
%
% The idea is simple, although it requires quite some work:
%
% If we stack plots on top of each other, early drawing commands
% (early plots) will be OVERDRAWN by later drawing commands (later
% plots). This is especially unfortunate if we use filled bar plots
% or comb plots.
%
% IDEA: draw plots in REVERSE order. The positioning, styles and
% whatever must not be affected, only the sequence of drawing commands
% shall change.
%
% So, this command here does all numerics which is to be done and
% assembles a NEW, REVERSED STORED PLOT LIST.
\def\pgfplots@stacked@finalize@stored@plots{%
	\pgfplotslistnewempty\pgfplots@stored@plotlist@reversed
	\begingroup
	\pgfplotslistforeachungrouped\pgfplots@stored@plotlist\as\pgfplots@loc@TMPa{%
		\expandafter\pgfplots@stored@plotlist@EXTRACTENTRY\pgfplots@loc@TMPa
		\ifx\pgfplots@stored@current@cmd\pgfutil@empty
		\else
			% Apply the data scaling transformation and compute
			% stacked coordinates, but do NOT
			% issue any drawing commands:
			\expandafter\pgfplots@stacked@finalize@stored@coords@START\pgfplots@stored@current@data
				\to
				{\pgfplots@stored@current@data}%
				{\pgfplots@stored@current@precmdappend}%
			% store preparation commands into "precmd":
			\t@pgfplots@tokb=\expandafter{\pgfplots@stored@current@precmd}%
			\t@pgfplots@toka=\expandafter{\pgfplots@stored@current@precmdappend}%
			\edef\pgfplots@stored@current@precmd{\the\t@pgfplots@tokb\the\t@pgfplots@toka}%
		\fi
		% Now, we need to insert all stored entities into the new,
		% reversed list. We only expand them ONCE.
		\t@pgfplots@toka=\expandafter{\pgfplots@stored@current@precmd}%
		\t@pgfplots@tokb=\expandafter{\pgfplots@stored@current@cmd}%
		\edef\pgfplots@loc@TMPa{%
			{\the\t@pgfplots@toka}{\the\t@pgfplots@tokb}}%
		\t@pgfplots@tokc=\expandafter{\pgfplots@loc@TMPa}%
		\t@pgfplots@toka=\expandafter{\pgfplots@stored@current@data}%
		\t@pgfplots@tokb=\expandafter{\pgfplots@stored@current@postcmd}%
		\edef\pgfplots@loc@TMPa{%
			\the\t@pgfplots@tokc
			{\the\t@pgfplots@toka}{\the\t@pgfplots@tokb}}%
		% Reverse sequence:
		\expandafter\pgfplotslistpushfront\pgfplots@loc@TMPa\to\pgfplots@stored@plotlist@reversed
	}%
	% Now, overwrite the original list:
	\global\let\pgfplots@stored@plotlist=\pgfplots@stored@plotlist@reversed
	\global\let\pgfplots@stored@plotlist@reversed=\relax
	\endgroup
}%

% This command finalizes the stored plot data. It records a coordinate
% stream into '#3' and assembles a macro '#4' which contains all
% preparation commands to ensure the functionality of
% \pgfplots@stacked@finalize@stored@plots
%
% Instead, it generates a macro #4 which - if used as "precommand"
% befor a draw operation - restores all required options and performs
% pre-drawing.
\long\def\pgfplots@stacked@finalize@stored@coords@START plot coordinates #1#2;\to#3#4{%
	\pgfplots@stacked@beginplot
	\pgfplots@coord@stream@INIT@finalize@stackedcoords@recordto{#3}{\pgfplots@recorded@marker@stream}%
	\pgfplots@coord@stream@foreach{#1}%
	\pgfplots@stacked@endplot
	\pgfplots@stacked@savestateto\pgfplots@loc@TMPa
	\t@pgfplots@toka=\expandafter{\pgfplots@loc@TMPa\def\pgfplots@stacked@stored@postpath{#2}}%
	\pgfplots@addplot@get@named@startendpoints@command\pgfplots@loc@TMPa
	\t@pgfplots@tokc=\expandafter{\pgfplots@loc@TMPa}%
	\ifpgfplots@record@marker@stream
		\t@pgfplots@tokb=\expandafter{\pgfplots@recorded@marker@stream}%
	\else
		\t@pgfplots@tokb={}%
	\fi
	\edef#4{%
		\the\t@pgfplots@tokc
		\noexpand\gdef\noexpand\pgfplots@recorded@marker@stream{\the\t@pgfplots@tokb}%
		\the\t@pgfplots@toka
	}%
}%

% #1: for coordinates
% #2: for markers
\def\pgfplots@coord@stream@INIT@finalize@stackedcoords@recordto#1#2{%
	\pgfplots@record@marker@streamtrue
	%
	\def\pgfplots@coord@stream@start@{%
		\gdef#1{\pgfplotstreamstart}%
		\ifpgfplots@record@marker@stream
			\pgfplotsapplistXnewempty\pgfplots@stacked@record@mark@cmds
			\pgfplotsapplistXpushback\pgfplotstreamstart\to\pgfplots@stacked@record@mark@cmds
		\fi
	}%
	\def\pgfplots@coord@stream@end@{%
		\expandafter\gdef\expandafter#1\expandafter{#1\pgfplotstreamend}%
		\ifpgfplots@record@marker@stream
			\pgfplotsapplistXpushback\pgfplotstreamend\to\pgfplots@stacked@record@mark@cmds
			\pgfplotsapplistXlet\pgfplots@loc@TMPa=\pgfplots@stacked@record@mark@cmds
			\global\let#2=\pgfplots@loc@TMPa
		\fi
	}%
	\ifpgfplots@apply@datatrafo
		\def\pgfplots@coord@stream@coord@##1##2##3##4{%
			\pgfplots@apply@data@scaletrafo@to@one@point{##1}{##2}{##3}{##4}%
			\pgfplots@coord@stream@finalize@currentpt
		}%
	\else
		\def\pgfplots@coord@stream@coord@##1##2##3##4{%
			\def\pgfplots@current@point@x{##1}%
			\def\pgfplots@current@point@y{##2}%
			\pgfplots@coord@stream@finalize@currentpt
		}%
	\fi
	\def\pgfplots@coord@stream@finalize@currentpt{%
		\pgfqpointxy{\pgfplots@current@point@x}{\pgfplots@current@point@y}%
		\edef\pgfmathresult{{\the\pgf@x}{\the\pgf@y}}%
		\t@pgfplots@toka=\expandafter{#1}%
		\t@pgfplots@tokb=\expandafter{\pgfmathresult}%
		\xdef#1{\the\t@pgfplots@toka
			\noexpand\pgfplots@stream\the\t@pgfplots@tokb}%
		%
		\ifpgfplots@record@marker@stream
			\ifdim\pgf@x<\pgfplots@xcoordminTEX
			\else
				\ifdim\pgf@x>\pgfplots@xcoordmaxTEX
				\else
					\ifdim\pgf@y<\pgfplots@ycoordminTEX
					\else
						\ifdim\pgf@y>\pgfplots@ycoordmaxTEX
						\else
							\edef\pgfmathresult{\noexpand\pgfplots@stream{\the\pgf@x}{\the\pgf@y}}%
							\expandafter\pgfplotsapplistXpushback\expandafter{\pgfmathresult}\to\pgfplots@stacked@record@mark@cmds%
						\fi
					\fi
				\fi
			\fi
		\fi
	}%
}

% This command gets called after the sequence reversal has been done.
% It unpacks everything prepared by 
% \pgfplots@stacked@finalize@stored@coords@START
% and draws the plot (and markers).
\def\pgfplots@stacked@draw@reversed@plot{%
	\pgfplots@stored@current@cmd[current plot style]
	\pgfextra
		\tikzset{every plot/.try}%
		\pgfplots@getcurrent@plothandler\pgfplots@basiclevel@plothandler
		\pgfplots@basiclevel@plothandler
		% this here contains a recorded plot stream, see above. 
		\pgfplots@stored@current@data
		%
		\pgfplots@assert@tikzinternal@exists{tikz@make@last@position}%
		\tikz@make@last@position{\pgfplotlastpoint}%  
	\expandafter
	\endpgfextra
	\pgfplots@stacked@stored@postpath
	;
	% this here has been assigned by the precommand as well.
	\ifx\pgfplots@recorded@marker@stream\pgfutil@empty
	\else
		\ifpgfplots@clip@marker@paths
			\pgfplots@stored@current@cmd[current plot style]
			\pgfextra 
				\pgfplots@install@plotmark@handler
				\pgfplots@recorded@marker@stream 
			\endpgfextra
			;
		\else
			\pgfplots@stored@REMEMBER@MARK@COMMAND
		\fi
	\fi
	\gdef\pgfplots@recorded@marker@stream{}% clear
}%


\def\pgfplots@stacked@path@closed@cycle{%
	\pgfplots@stacked@closedcycle@impl
}

% Saves the finalized variables into macro #1 such that a call to #1
% restores them.
%
% This affects pgf zero level handlers and whether this here is the
% first plot or not..
\def\pgfplots@stacked@savestateto#1{%
	\t@pgfplots@toka=\expandafter{\pgfplots@stacked@PGFzerolevels}%
	\ifpgfplots@stacked@isfirstplot
		\t@pgfplots@tokb={\pgfplots@stacked@isfirstplottrue}%
	\else
		\t@pgfplots@tokb={\pgfplots@stacked@isfirstplotfalse}%
	\fi
	\t@pgfplots@tokc=\expandafter{\pgfplots@stacked@closedcycle@impl}%
	\edef#1{%
		\noexpand\gdef\noexpand\pgfplots@stacked@PGFzerolevels{\the\t@pgfplots@toka}%
		\the\t@pgfplots@tokb
		\noexpand\def\noexpand\pgfplots@stacked@closedcycle@impl{\the\t@pgfplots@tokc}%
	}%
}

% PGF interfaces:
\def\pgfplotxzerolevelstream@@list{%
	\def\pgf@plotxzerolevelstreamstart{%
		\global\let\pgfplotxzerolevelstream@@list@@backup=\pgfplots@stacked@PGFzerolevels
		\gdef\pgf@plotxzerolevelstreamnext{%
			\pgfplotslistcheckempty\pgfplots@stacked@PGFzerolevels
			\ifpgfplotslistempty
				\global\pgf@x=\pgfplots@ZERO@x\relax
			\else
				{\globaldefs=1\relax
				\pgfplotslistpopfront\pgfplots@stacked@PGFzerolevels\to\pgfmathresult
				}%
				\global\pgf@x=\pgfmathresult\relax
			\fi
		}%
	}%
	\def\pgf@plotxzerolevelstreamend{%
		\global\let\pgfplots@stacked@PGFzerolevels=\pgfplotxzerolevelstream@@list@@backup
	}%
}%

\def\pgfplotyzerolevelstream@@list{%
	\def\pgf@plotyzerolevelstreamstart{%
		\global\let\pgfplotyzerolevelstream@@list@@backup=\pgfplots@stacked@PGFzerolevels
		\gdef\pgf@plotyzerolevelstreamnext{%
			\pgfplotslistcheckempty\pgfplots@stacked@PGFzerolevels
			\ifpgfplotslistempty
				\global\pgf@x=\pgfplots@ZERO@y\relax
			\else
				{\globaldefs=1\relax
				\pgfplotslistpopfront\pgfplots@stacked@PGFzerolevels\to\pgfmathresult
				}%
				\global\pgf@x=\pgfmathresult\relax
			\fi
		}%
	}%
	\def\pgf@plotyzerolevelstreamend{%
		\global\let\pgfplots@stacked@PGFzerolevels=\pgfplotyzerolevelstream@@list@@backup
	}%
}%
