-
-
Save anonymous/85c63d9619476896765f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% | |
%% This is file `forest.sty', | |
%% generated with the docstrip utility. | |
%% | |
%% The original source files were: | |
%% | |
%% forest.dtx | |
%% | |
%% `forest' is a `pgf/tikz'-based package for drawing (linguistic) trees. | |
%% | |
%% Copyright (c) 2012 Saso Zivanovic | |
%% (Sa\v{s}o \v{Z}ivanovi\'{c}) | |
%% saso.zivanovic@guest.arnes.si | |
%% | |
%% This work may be distributed and/or modified under the | |
%% conditions of the LaTeX Project Public License, either version 1.3 | |
%% of this license or (at your option) any later version. | |
%% The latest version of this license is in | |
%% | |
%% http://www.latex-project.org/lppl.txt | |
%% | |
%% and version 1.3 or later is part of all distributions of LaTeX | |
%% version 2005/12/01 or later. | |
%% | |
%% This work has the LPPL maintenance status `maintained'. | |
%% | |
%% The Current Maintainer of this work is Saso Zivanovic. | |
%% | |
%% This work consists of the files forest.dtx and forest.ins | |
%% and the derived file forest.sty. | |
%% | |
\ProvidesPackage{forest}[2013/01/28 v1.03 Drawing (linguistic) trees] | |
\RequirePackage{tikz}[2010/10/13] | |
\usetikzlibrary{shapes} | |
\usetikzlibrary{fit} | |
\usetikzlibrary{calc} | |
\usepgflibrary{intersections} | |
\RequirePackage{pgfopts} | |
\RequirePackage{etoolbox}[2010/08/21] | |
\RequirePackage{environ} | |
%\usepackage[trace]{trace-pgfkeys} | |
\pgfkeys{/forest/.is family} | |
\def\forestset#1{\pgfqkeys{/forest}{#1}} | |
\long\def\forest@original@pgfkeysdefnargs@#1#2#3#4{% | |
\ifcase#2\relax | |
\pgfkeyssetvalue{#1/.@args}{}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8##9}% | |
\else | |
\pgfkeys@error{\string\pgfkeysdefnargs: expected <= 9 arguments, got #2}% | |
\fi | |
\pgfkeysgetvalue{#1/.@args}\pgfkeys@tempargs | |
\def\pgfkeys@temp{\expandafter#4\csname pgfk@#1/.@@body\endcsname}% | |
\expandafter\pgfkeys@temp\pgfkeys@tempargs{#3}% | |
% eliminate the \pgfeov at the end such that TeX gobbles spaces | |
% by using | |
% \pgfkeysdef{#1}{\pgfkeysvalueof{#1/.@@body}##1} | |
% (with expansion of '#1'): | |
\edef\pgfkeys@tempargs{\noexpand\pgfkeysvalueof{#1/.@@body}}% | |
\def\pgfkeys@temp{\pgfkeysdef{#1}}% | |
\expandafter\pgfkeys@temp\expandafter{\pgfkeys@tempargs##1}% | |
\pgfkeyssetvalue{#1/.@body}{#3}% | |
} | |
\long\def\forest@patched@pgfkeysdefnargs@#1#2#3#4{% | |
\ifcase#2\relax | |
\pgfkeyssetvalue{#1/.@args}{}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}% | |
%%%%% removed: | |
%%%%% \or | |
%%%%% \pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8}% | |
\or | |
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8##9}% | |
\else | |
\pgfkeys@error{\string\pgfkeysdefnargs: expected <= 9 arguments, got #2}% | |
\fi | |
\pgfkeysgetvalue{#1/.@args}\pgfkeys@tempargs | |
\def\pgfkeys@temp{\expandafter#4\csname pgfk@#1/.@@body\endcsname}% | |
\expandafter\pgfkeys@temp\pgfkeys@tempargs{#3}% | |
% eliminate the \pgfeov at the end such that TeX gobbles spaces | |
% by using | |
% \pgfkeysdef{#1}{\pgfkeysvalueof{#1/.@@body}##1} | |
% (with expansion of '#1'): | |
\edef\pgfkeys@tempargs{\noexpand\pgfkeysvalueof{#1/.@@body}}% | |
\def\pgfkeys@temp{\pgfkeysdef{#1}}% | |
\expandafter\pgfkeys@temp\expandafter{\pgfkeys@tempargs##1}% | |
\pgfkeyssetvalue{#1/.@body}{#3}% | |
} | |
\ifx\pgfkeysdefnargs@\forest@original@pgfkeysdefnargs@ | |
\let\pgfkeysdefnargs@\forest@patched@pgfkeysdefnargs@ | |
\fi | |
\def\forest@original@pgfpointintersectionoflines#1#2#3#4{% | |
{ | |
% | |
% Compute orthogonal vector to #1--#2 | |
% | |
\pgf@process{#2}% | |
\pgf@xa=\pgf@x% | |
\pgf@ya=\pgf@y% | |
\pgf@process{#1}% | |
\advance\pgf@xa by-\pgf@x% | |
\advance\pgf@ya by-\pgf@y% | |
\pgf@ya=-\pgf@ya% | |
% Normalise a bit | |
\c@pgf@counta=\pgf@xa% | |
\ifnum\c@pgf@counta<0\relax% | |
\c@pgf@counta=-\c@pgf@counta\relax% | |
\fi% | |
\c@pgf@countb=\pgf@ya% | |
\ifnum\c@pgf@countb<0\relax% | |
\c@pgf@countb=-\c@pgf@countb\relax% | |
\fi% | |
\advance\c@pgf@counta by\c@pgf@countb\relax% | |
\divide\c@pgf@counta by 65536\relax% | |
\ifnum\c@pgf@counta>0\relax% | |
\divide\pgf@xa by\c@pgf@counta\relax% | |
\divide\pgf@ya by\c@pgf@counta\relax% | |
\fi% | |
% | |
% Compute projection | |
% | |
\pgf@xc=\pgf@sys@tonumber{\pgf@ya}\pgf@x% | |
\advance\pgf@xc by\pgf@sys@tonumber{\pgf@xa}\pgf@y% | |
% | |
% The orthogonal vector is (\pgf@ya,\pgf@xa) | |
% | |
% | |
% Compute orthogonal vector to #3--#4 | |
% | |
\pgf@process{#4}% | |
\pgf@xb=\pgf@x% | |
\pgf@yb=\pgf@y% | |
\pgf@process{#3}% | |
\advance\pgf@xb by-\pgf@x% | |
\advance\pgf@yb by-\pgf@y% | |
\pgf@yb=-\pgf@yb% | |
% Normalise a bit | |
\c@pgf@counta=\pgf@xb% | |
\ifnum\c@pgf@counta<0\relax% | |
\c@pgf@counta=-\c@pgf@counta\relax% | |
\fi% | |
\c@pgf@countb=\pgf@yb% | |
\ifnum\c@pgf@countb<0\relax% | |
\c@pgf@countb=-\c@pgf@countb\relax% | |
\fi% | |
\advance\c@pgf@counta by\c@pgf@countb\relax% | |
\divide\c@pgf@counta by 65536\relax% | |
\ifnum\c@pgf@counta>0\relax% | |
\divide\pgf@xb by\c@pgf@counta\relax% | |
\divide\pgf@yb by\c@pgf@counta\relax% | |
\fi% | |
% | |
% Compute projection | |
% | |
\pgf@yc=\pgf@sys@tonumber{\pgf@yb}\pgf@x% | |
\advance\pgf@yc by\pgf@sys@tonumber{\pgf@xb}\pgf@y% | |
% | |
% The orthogonal vector is (\pgf@yb,\pgf@xb) | |
% | |
% Setup transformation matrx (this is just to use the matrix | |
% inversion) | |
% | |
\pgfsettransform{{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@yb}{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@xb}{0pt}{0pt}}% | |
\pgftransforminvert% | |
\pgf@process{\pgfpointtransformed{\pgfpoint{\pgf@xc}{\pgf@yc}}}% | |
}% | |
} | |
\def\forest@patched@pgfpointintersectionoflines#1#2#3#4{% | |
{% added the percent sign in this line | |
% | |
% Compute orthogonal vector to #1--#2 | |
% | |
\pgf@process{#2}% | |
\pgf@xa=\pgf@x% | |
\pgf@ya=\pgf@y% | |
\pgf@process{#1}% | |
\advance\pgf@xa by-\pgf@x% | |
\advance\pgf@ya by-\pgf@y% | |
\pgf@ya=-\pgf@ya% | |
% Normalise a bit | |
\c@pgf@counta=\pgf@xa% | |
\ifnum\c@pgf@counta<0\relax% | |
\c@pgf@counta=-\c@pgf@counta\relax% | |
\fi% | |
\c@pgf@countb=\pgf@ya% | |
\ifnum\c@pgf@countb<0\relax% | |
\c@pgf@countb=-\c@pgf@countb\relax% | |
\fi% | |
\advance\c@pgf@counta by\c@pgf@countb\relax% | |
\divide\c@pgf@counta by 65536\relax% | |
\ifnum\c@pgf@counta>0\relax% | |
\divide\pgf@xa by\c@pgf@counta\relax% | |
\divide\pgf@ya by\c@pgf@counta\relax% | |
\fi% | |
% | |
% Compute projection | |
% | |
\pgf@xc=\pgf@sys@tonumber{\pgf@ya}\pgf@x% | |
\advance\pgf@xc by\pgf@sys@tonumber{\pgf@xa}\pgf@y% | |
% | |
% The orthogonal vector is (\pgf@ya,\pgf@xa) | |
% | |
% | |
% Compute orthogonal vector to #3--#4 | |
% | |
\pgf@process{#4}% | |
\pgf@xb=\pgf@x% | |
\pgf@yb=\pgf@y% | |
\pgf@process{#3}% | |
\advance\pgf@xb by-\pgf@x% | |
\advance\pgf@yb by-\pgf@y% | |
\pgf@yb=-\pgf@yb% | |
% Normalise a bit | |
\c@pgf@counta=\pgf@xb% | |
\ifnum\c@pgf@counta<0\relax% | |
\c@pgf@counta=-\c@pgf@counta\relax% | |
\fi% | |
\c@pgf@countb=\pgf@yb% | |
\ifnum\c@pgf@countb<0\relax% | |
\c@pgf@countb=-\c@pgf@countb\relax% | |
\fi% | |
\advance\c@pgf@counta by\c@pgf@countb\relax% | |
\divide\c@pgf@counta by 65536\relax% | |
\ifnum\c@pgf@counta>0\relax% | |
\divide\pgf@xb by\c@pgf@counta\relax% | |
\divide\pgf@yb by\c@pgf@counta\relax% | |
\fi% | |
% | |
% Compute projection | |
% | |
\pgf@yc=\pgf@sys@tonumber{\pgf@yb}\pgf@x% | |
\advance\pgf@yc by\pgf@sys@tonumber{\pgf@xb}\pgf@y% | |
% | |
% The orthogonal vector is (\pgf@yb,\pgf@xb) | |
% | |
% Setup transformation matrx (this is just to use the matrix | |
% inversion) | |
% | |
\pgfsettransform{{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@yb}{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@xb}{0pt}{0pt}}% | |
\pgftransforminvert% | |
\pgf@process{\pgfpointtransformed{\pgfpoint{\pgf@xc}{\pgf@yc}}}% | |
}% | |
} | |
\ifx\pgfpointintersectionoflines\forest@original@pgfpointintersectionoflines | |
\let\pgfpointintersectionoflines\forest@patched@pgfpointintersectionoflines | |
\fi | |
% hah: hacking forest --- it depends on some details of PGF implementation | |
\def\forest@pgf@notyetpositioned{not yet positionedPGFINTERNAL}% | |
\expandafter\ifstrequal\expandafter{\pgfversion}{2.10}{% | |
\def\forest@pgf@notyetpositioned{not yet positioned@}% | |
}{} | |
\long\def\@escapeif#1#2\fi{\fi#1} | |
\long\def\@escapeifif#1#2\fi#3\fi{\fi\fi#1} | |
\def\newloop#1{% | |
\count@=\escapechar | |
\escapechar=-1 | |
\expandafter\newloop@parse@loopname\string#1\newloop@end | |
\escapechar=\count@ | |
}% | |
{\lccode`7=`l \lccode`8=`o \lccode`9=`p | |
\lowercase{\gdef\newloop@parse@loopname#17889#2\newloop@end{% | |
\edef\newloop@marshal{% | |
\noexpand\csdef{#1loop#2}####1\expandafter\noexpand\csname #1repeat#2\endcsname{% | |
\noexpand\csdef{#1iterate#2}{####1\relax\noexpand\expandafter\expandafter\noexpand\csname#1iterate#2\endcsname\noexpand\fi}% | |
\expandafter\noexpand\csname#1iterate#2\endcsname | |
\let\expandafter\noexpand\csname#1iterate#2\endcsname\relax | |
}% | |
}% | |
\newloop@marshal | |
}% | |
}% | |
}% | |
\newloop\forest@loop | |
\newloop\forest@loopa | |
\newloop\forest@loopb | |
\newloop\forest@loopc | |
\newloop\forest@sort@loop | |
\newloop\forest@sort@loopA | |
\newdimen\forest@temp@dimen | |
\newcount\forest@temp@count | |
\newcount\forest@n | |
\newif\ifforest@temp | |
\newcount\forest@temp@global@count | |
\def\apptotoks#1#2{\expandafter#1\expandafter{\the#1#2}} | |
\long\def\lapptotoks#1#2{\expandafter#1\expandafter{\the#1#2}} | |
\def\eapptotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\pot@temp}} | |
\def\pretotoks#1#2{\toks@={#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@\the#1}} | |
\def\epretotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\pot@temp\the#1}} | |
\def\gapptotoks#1#2{\expandafter\global\expandafter#1\expandafter{\the#1#2}} | |
\def\xapptotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\pot@temp}} | |
\def\gpretotoks#1#2{\toks@={#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@\the#1}} | |
\def\xpretotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\pot@temp\the#1}} | |
\def\expandnumberarg#1#2{\expandafter#1\expandafter{\number#2}} | |
\def\expandtwonumberargs#1#2#3{% | |
\expandafter\expandtwonumberargs@\expandafter#1\expandafter{\number#3}{#2}} | |
\def\expandtwonumberargs@#1#2#3{% | |
\expandafter#1\expandafter{\number#3}{#2}} | |
\def\expandthreenumberargs#1#2#3#4{% | |
\expandafter\expandthreenumberargs@\expandafter#1\expandafter{\number#4}{#2}{#3}} | |
\def\expandthreenumberargs@#1#2#3#4{% | |
\expandafter\expandthreenumberargs@@\expandafter#1\expandafter{\number#4}{#2}{#3}} | |
\def\expandthreenumberargs@@#1#2#3#4{% | |
\expandafter#1\expandafter{\number#4}{#2}{#3}} | |
\def\forest@convert@others@to@underscores#1#2{% | |
\def\forest@cotu@result{}% | |
\forest@cotu#1\forest@end | |
\let#2\forest@cotu@result | |
} | |
\def\forest@cotu{% | |
\futurelet\forest@cotu@nextchar\forest@cotu@checkforspace | |
} | |
\def\forest@cotu@checkforspace{% | |
\expandafter\ifx\space\forest@cotu@nextchar | |
\let\forest@cotu@next\forest@cotu@havespace | |
\else | |
\let\forest@cotu@next\forest@cotu@nospace | |
\fi | |
\forest@cotu@next | |
} | |
\def\forest@cotu@havespace#1{% | |
\appto\forest@cotu@result{_}% | |
\forest@cotu#1% | |
} | |
\def\forest@cotu@nospace{% | |
\ifx\forest@cotu@nextchar\forest@end | |
\@escapeif\@gobble | |
\else | |
\@escapeif\forest@cotu@nospaceB | |
\fi | |
} | |
\def\forest@cotu@nospaceB{% | |
\ifcat\forest@cotu@nextchar a% | |
\let\forest@cotu@next\forest@cotu@have@alphanum | |
\else | |
\ifcat\forest@cotu@nextchar 0% | |
\let\forest@cotu@next\forest@cotu@have@alphanum | |
\else | |
\let\forest@cotu@next\forest@cotu@haveother | |
\fi | |
\fi | |
\forest@cotu@next | |
} | |
\def\forest@cotu@have@alphanum#1{% | |
\appto\forest@cotu@result{#1}% | |
\forest@cotu | |
} | |
\def\forest@cotu@haveother#1{% | |
\appto\forest@cotu@result{_}% | |
\forest@cotu | |
} | |
\def\forest@listedel#1#2{% #1 = list, #2 = item | |
\edef\forest@marshal{\noexpand\forest@listdel\noexpand#1{#2}}% | |
\forest@marshal | |
} | |
\def\forest@listcsdel#1#2{% | |
\expandafter\forest@listdel\csname #1\endcsname{#2}% | |
} | |
\def\forest@listcsedel#1#2{% | |
\expandafter\forest@listedel\csname #1\endcsname{#2}% | |
} | |
\edef\forest@restorelistsepcatcode{\noexpand\catcode`|\the\catcode`|\relax}% | |
\catcode`\|=3 | |
\gdef\forest@listdel#1#2{% | |
\def\forest@listedel@A##1|#2|##2\forest@END{% | |
\forest@listedel@B##1|##2\forest@END%| | |
}% | |
\def\forest@listedel@B|##1\forest@END{%| | |
\def#1{##1}% | |
}% | |
\expandafter\forest@listedel@A\expandafter|#1\forest@END%| | |
} | |
\forest@restorelistsepcatcode | |
\def\forest@strip@braces#1{% | |
\forest@strip@braces@A#1\forest@strip@braces@preend\forest@strip@braces@end | |
} | |
\def\forest@strip@braces@A#1#2\forest@strip@braces@end{% | |
#1\ifx\forest@strip@braces@preend#2\else\@escapeif{\forest@strip@braces@A#2\forest@strip@braces@end}\fi | |
} | |
\def\forest@sort#1#2#3#4#5{% | |
\let\forest@sort@cmp#1\relax | |
\let\forest@sort@let#2\relax | |
\let\forest@sort@direction#3\relax | |
\forest@@sort{#4}{#5}% | |
} | |
\def\forest@quicksort@minarraylength{10000} | |
\def\forest@@sort#1#2{% | |
\ifnum#1<#2\relax\@escapeif{% | |
\forest@sort@m=#2 | |
\advance\forest@sort@m -#1 | |
\ifnum\forest@sort@m>\forest@quicksort@minarraylength\relax\@escapeif{% | |
\forest@quicksort{#1}{#2}% | |
}\else\@escapeif{% | |
\forest@insertionsort{#1}{#2}% | |
}\fi | |
}\fi | |
} | |
\newcount\forest@sort@m\newcount\forest@sort@k\newcount\forest@sort@p | |
\def\forest@sort@ascending{>} | |
\def\forest@sort@descending{<} | |
\def\forest@sort@cmp{% | |
\PackageError{sort}{You must define forest@sort@cmp function before calling | |
sort}{The macro must take two arguments, indices of the array | |
elements to be compared, and return '=' if the elements are equal | |
and '>'/'<' if the first is greater /less than the secong element.}% | |
} | |
\def\forest@sort@cmp@gt{\def\forest@sort@cmp@result{>}} | |
\def\forest@sort@cmp@lt{\def\forest@sort@cmp@result{<}} | |
\def\forest@sort@cmp@eq{\def\forest@sort@cmp@result{=}} | |
\def\forest@sort@let{% | |
\PackageError{sort}{You must define forest@sort@let function before calling | |
sort}{The macro must take two arguments, indices of the array: | |
element 2 must be copied onto element 1.}% | |
} | |
\def\forest@quicksort#1#2{% | |
\forest@sort@m=#2 | |
\advance\forest@sort@m -#1 | |
\ifodd\forest@sort@m\relax\advance\forest@sort@m1 \fi | |
\divide\forest@sort@m 2 | |
\advance\forest@sort@m #1 | |
\forest@sort@cmp{#1}{#2}% | |
\if\forest@sort@cmp@result=% | |
\forest@sort@p=#1 | |
\else | |
\if\forest@sort@cmp@result>% | |
\forest@sort@p=#1\relax | |
\else | |
\forest@sort@p=#2\relax | |
\fi | |
\forest@sort@cmp{\the\forest@sort@p}{\the\forest@sort@m}% | |
\if\forest@sort@cmp@result<% | |
\else | |
\forest@sort@p=\the\forest@sort@m | |
\fi | |
\fi | |
\forest@sort@xch{#1}{\the\forest@sort@p}% | |
\forest@sort@m=#1\relax | |
\forest@sort@k=#1\relax | |
\forest@sort@loop | |
\ifnum\forest@sort@k<#2\relax | |
\advance\forest@sort@k 1 | |
\forest@sort@cmp{#1}{\the\forest@sort@k}% | |
\ifx\forest@sort@direction\forest@sort@cmp@result | |
\advance\forest@sort@m 1 | |
\forest@sort@xch{\the\forest@sort@m}{\the\forest@sort@k} | |
\fi | |
\forest@sort@repeat | |
\forest@sort@xch{#1}{\the\forest@sort@m}% | |
\forest@sort@k=\forest@sort@m | |
\advance\forest@sort@k -1 | |
\advance\forest@sort@m 1 | |
\edef\forest@sort@marshal{% | |
\noexpand\forest@@sort{#1}{\the\forest@sort@k}% | |
\noexpand\forest@@sort{\the\forest@sort@m}{#2}% | |
}% | |
\forest@sort@marshal | |
} | |
\def\forest@sort@xch#1#2{% | |
\forest@sort@let{aux}{#1}% | |
\forest@sort@let{#1}{#2}% | |
\forest@sort@let{#2}{aux}% | |
} | |
\def\forest@insertionsort#1#2{% | |
\forest@sort@m=#1 | |
\edef\forest@insertionsort@low{#1}% | |
\forest@sort@loopA | |
\ifnum\forest@sort@m<#2 | |
\advance\forest@sort@m 1 | |
\forest@insertionsort@Qbody | |
\forest@sort@repeatA | |
} | |
\newif\ifforest@insertionsort@loop | |
\def\forest@insertionsort@Qbody{% | |
\forest@sort@let{aux}{\the\forest@sort@m}% | |
\forest@sort@k\forest@sort@m | |
\advance\forest@sort@k -1 | |
\forest@insertionsort@looptrue | |
\forest@sort@loop | |
\ifforest@insertionsort@loop | |
\forest@insertionsort@qbody | |
\forest@sort@repeat | |
\advance\forest@sort@k 1 | |
\forest@sort@let{\the\forest@sort@k}{aux}% | |
} | |
\def\forest@insertionsort@qbody{% | |
\forest@sort@cmp{\the\forest@sort@k}{aux}% | |
\ifx\forest@sort@direction\forest@sort@cmp@result\relax | |
\forest@sort@p=\forest@sort@k | |
\advance\forest@sort@p 1 | |
\forest@sort@let{\the\forest@sort@p}{\the\forest@sort@k}% | |
\advance\forest@sort@k -1 | |
\ifnum\forest@sort@k<\forest@insertionsort@low\relax | |
\forest@insertionsort@loopfalse | |
\fi | |
\else | |
\forest@insertionsort@loopfalse | |
\fi | |
} | |
\def\forest@sort@cmpnumcs#1#2{% | |
\ifnum\csname#1\endcsname>\csname#2\endcsname\relax | |
\forest@sort@cmp@gt | |
\else | |
\ifnum\csname#1\endcsname<\csname#2\endcsname\relax | |
\forest@sort@cmp@lt | |
\else | |
\forest@sort@cmp@eq | |
\fi | |
\fi | |
} | |
\def\forest@sort@cmpdimcs#1#2{% | |
\ifdim\csname#1\endcsname>\csname#2\endcsname\relax | |
\forest@sort@cmp@gt | |
\else | |
\ifdim\csname#1\endcsname<\csname#2\endcsname\relax | |
\forest@sort@cmp@lt | |
\else | |
\forest@sort@cmp@eq | |
\fi | |
\fi | |
} | |
\def\forest@sort@cmptwodimcs#1#2#3#4{% | |
\ifdim\csname#1\endcsname>\csname#3\endcsname\relax | |
\forest@sort@cmp@gt | |
\else | |
\ifdim\csname#1\endcsname<\csname#3\endcsname\relax | |
\forest@sort@cmp@lt | |
\else | |
\ifdim\csname#2\endcsname>\csname#4\endcsname\relax | |
\forest@sort@cmp@gt | |
\else | |
\ifdim\csname#2\endcsname<\csname#4\endcsname\relax | |
\forest@sort@cmp@lt | |
\else | |
\forest@sort@cmp@eq | |
\fi | |
\fi | |
\fi | |
\fi | |
} | |
\def\forest@reversearray#1#2#3{% | |
\let\forest@sort@let#1% | |
\c@pgf@countc=#2 | |
\c@pgf@countd=#3 | |
\advance\c@pgf@countd -1 | |
\forest@loopa | |
\ifnum\c@pgf@countc<\c@pgf@countd\relax | |
\forest@sort@xch{\the\c@pgf@countc}{\the\c@pgf@countd}% | |
\advance\c@pgf@countc 1 | |
\advance\c@pgf@countd -1 | |
\forest@repeata | |
} | |
\def\bracketset#1{\pgfqkeys{/bracket}{#1}}% | |
\bracketset{% | |
/bracket/.is family, | |
/handlers/.let/.style={\pgfkeyscurrentpath/.code={\let#1##1}}, | |
opening bracket/.let=\bracket@openingBracket, | |
closing bracket/.let=\bracket@closingBracket, | |
action character/.let=\bracket@actionCharacter, | |
opening bracket=[, | |
closing bracket=], | |
action character, | |
new node/.code n args={3}{% #1=preamble, #2=node spec, #3=cs receiving the id | |
\forest@node@new#3% | |
\forestOset{#3}{given options}{content'=#2}% | |
\ifblank{#1}{}{% | |
\forestOpreto{#3}{given options}{#1,}% | |
}% | |
}, | |
set afterthought/.code 2 args={% #1=node id, #2=afterthought | |
\ifblank{#2}{}{\forestOappto{#1}{given options}{,afterthought={#2}}}% | |
} | |
} | |
\newtoks\bracket@content | |
\newtoks\bracket@afterthought | |
\def\bracketParse#1#2={% | |
\def\bracketEndParsingHook{#1}% | |
\def\bracket@saveRootNodeTo{#2}% | |
\bracket@content={}% | |
\bracket@afterthought={}% | |
\let\bracket@state\bracket@state@starting | |
\bracket@ignorespacestrue | |
\bracket@expandtokensfalse | |
\def\bracket@parentNode{0}% | |
\def\bracket@rootNode{0}% | |
\def\bracket@newNode{0}% | |
\def\bracket@afterthoughtNode{0}% | |
\bracket@Parse | |
} | |
\def\bracketResume{\bracket@Parse}% | |
\def\bracket@Parse{% | |
\futurelet\bracket@next@token\bracket@Parse@checkForSpace | |
} | |
\def\bracket@Parse@checkForSpace{% | |
\expandafter\ifx\space\bracket@next@token\@escapeif{% | |
\ifbracket@ignorespaces\else | |
\bracket@haveSpacetrue | |
\fi | |
\expandafter\bracket@Parse\romannumeral-`0% | |
}\else\@escapeif{% | |
\bracket@Parse@maybeexpand | |
}\fi | |
} | |
\newif\ifbracket@expandtokens | |
\def\bracket@Parse@maybeexpand{% | |
\ifbracket@expandtokens\@escapeif{% | |
\expandafter\bracket@Parse@peekAhead\romannumeral-`0% | |
}\else\@escapeif{% | |
\bracket@Parse@peekAhead | |
}\fi | |
} | |
\def\bracket@Parse@peekAhead{% | |
\futurelet\bracket@next@token\bracket@Parse@checkForTeXGroup | |
} | |
\def\bracket@Parse@checkForTeXGroup{% | |
\ifx\bracket@next@token\bgroup% | |
\@escapeif{\bracket@Parse@appendGroup}% | |
\else | |
\@escapeif{\bracket@Parse@token}% | |
\fi | |
} | |
\long\def\bracket@Parse@token#1{% | |
\ifx#1\bracket@openingBracket | |
\@escapeif{\bracket@Parse@openingBracketFound}% | |
\else | |
\@escapeif{% | |
\ifx#1\bracket@closingBracket | |
\@escapeif{\bracket@Parse@closingBracketFound}% | |
\else | |
\@escapeif{% | |
\ifx#1\bracket@actionCharacter | |
\@escapeif{\futurelet\bracket@next@token\bracket@Parse@actionCharacterFound}% | |
\else | |
\@escapeif{\bracket@Parse@appendToken#1}% | |
\fi | |
}% | |
\fi | |
}% | |
\fi | |
} | |
\newif\ifbracket@haveSpace | |
\newif\ifbracket@ignorespaces | |
\def\bracket@Parse@appendSpace{% | |
\ifbracket@haveSpace | |
\ifcase\bracket@state\relax | |
\eapptotoks\bracket@content\space | |
\or | |
\eapptotoks\bracket@afterthought\space | |
\or | |
\eapptotoks\bracket@afterthought\space | |
\fi | |
\bracket@haveSpacefalse | |
\fi | |
} | |
\long\def\bracket@Parse@appendToken#1{% | |
\bracket@Parse@appendSpace | |
\ifcase\bracket@state\relax | |
\lapptotoks\bracket@content{#1}% | |
\or | |
\lapptotoks\bracket@afterthought{#1}% | |
\or | |
\lapptotoks\bracket@afterthought{#1}% | |
\fi | |
\bracket@ignorespacesfalse | |
\bracket@Parse | |
} | |
\def\bracket@Parse@appendGroup#1{% | |
\bracket@Parse@appendSpace | |
\ifcase\bracket@state\relax | |
\apptotoks\bracket@content{{#1}}% | |
\or | |
\apptotoks\bracket@afterthought{{#1}}% | |
\or | |
\apptotoks\bracket@afterthought{{#1}}% | |
\fi | |
\bracket@ignorespacesfalse | |
\bracket@Parse | |
} | |
\def\bracket@state@inContent{0} | |
\def\bracket@state@inAfterthought{1} | |
\def\bracket@state@starting{2} | |
\def\bracket@Parse@openingBracketFound{% | |
\bracket@haveSpacefalse | |
\ifcase\bracket@state\relax% in content [ ... [ | |
\@escapeif{% | |
\bracket@createNode | |
\ifnum\bracket@parentNode=0 \else | |
\forest@node@Append{\bracket@parentNode}{\bracket@newNode}% | |
\fi | |
\let\bracket@parentNode\bracket@newNode | |
\bracket@Parse | |
}% | |
\or % in afterthought ] ... [ | |
\@escapeif{% | |
\bracket@addAfterthought | |
\let\bracket@state\bracket@state@inContent | |
\bracket@Parse | |
}% | |
\else % starting | |
\@escapeif{% | |
\let\bracket@state\bracket@state@inContent | |
\bracket@Parse | |
}% | |
\fi | |
} | |
\def\bracket@Parse@closingBracketFound{% | |
\bracket@haveSpacefalse | |
\ifcase\bracket@state\relax % in content [ ... ] | |
\@escapeif{% | |
\bracket@createNode | |
\ifnum\bracket@parentNode=0 | |
\@escapeif\bracketEndParsingHook | |
\else | |
\@escapeif{% | |
\let\bracket@afterthoughtNode\bracket@newNode | |
\let\bracket@state\bracket@state@inAfterthought | |
\forest@node@Append{\bracket@parentNode}{\bracket@newNode}% | |
\bracket@Parse | |
}% | |
\fi | |
}% | |
\or % in afterthought ] ... ] | |
\@escapeif{% | |
\bracket@addAfterthought | |
\let\bracket@afterthoughtNode\bracket@parentNode | |
\edef\bracket@parentNode{\forestOve{\bracket@parentNode}{@parent}}% | |
\ifnum\bracket@parentNode=0 | |
\expandafter\bracketEndParsingHook | |
\else | |
\expandafter\bracket@Parse | |
\fi | |
}% | |
\else % starting | |
\PackageError{forest}{You're attempting to start a bracket representation | |
with a closing bracket}{}% | |
\fi | |
} | |
\def\bracket@Parse@actionCharacterFound{% | |
\ifx\bracket@next@token\bgroup\@escapeif{% | |
\bracket@Parse@action@expandgroup | |
}\else\@escapeif{% | |
\bracket@Parse@action@notagroup | |
}\fi | |
} | |
\def\bracket@Parse@action@expandgroup#1{% | |
\edef\bracket@Parse@action@expandgroup@macro{#1}% | |
\expandafter\bracket@Parse\bracket@Parse@action@expandgroup@macro | |
} | |
\let\bracket@action@fullyexpandCharacter+ | |
\let\bracket@action@dontexpandCharacter- | |
\let\bracket@action@executeCharacter! | |
\def\bracket@Parse@action@notagroup#1{% | |
\ifx#1\bracket@action@fullyexpandCharacter\@escapeif{% | |
\bracket@expandtokenstrue\bracket@Parse | |
}\else\@escapeif{% | |
\ifx#1\bracket@action@dontexpandCharacter\@escapeif{% | |
\bracket@expandtokensfalse\bracket@Parse | |
}\else\@escapeif{% | |
\ifx#10\@escapeif{% | |
\bracket@Parse@appendToken | |
}\else\@escapeif{% | |
\ifx#1\bracket@actionCharacter | |
\else\@escapeif{% | |
\expandafter\bracket@Parse#1% | |
}\fi | |
}\fi | |
}\fi | |
}\fi | |
} | |
\def\bracket@createNode{% | |
\ifnum\bracket@rootNode=0 | |
% root node | |
\bracketset{new node/.expanded=% | |
{\the\bracket@afterthought}% | |
{\the\bracket@content}% | |
\noexpand\bracket@newNode | |
}% | |
\bracket@afterthought={}% | |
\let\bracket@rootNode\bracket@newNode | |
\expandafter\let\bracket@saveRootNodeTo\bracket@newNode | |
\else | |
% other nodes | |
\bracketset{new node/.expanded=% | |
{}% | |
{\the\bracket@content}% | |
\noexpand\bracket@newNode | |
}% | |
\fi | |
\bracket@content={}% | |
} | |
\def\bracket@addAfterthought{% | |
\bracketset{% | |
set afterthought/.expanded={\bracket@afterthoughtNode}{\the\bracket@afterthought}% | |
}% | |
\bracket@afterthought={}% | |
} | |
% full expansion expands precisely to the value | |
\def\forestov#1{\expandafter\expandafter\expandafter\expandonce | |
\pgfkeysvalueof{/forest/@node/\forest@cn/#1}} | |
% full expansion expands all the way | |
\def\forestove#1{\pgfkeysvalueof{/forest/@node/\forest@cn/#1}} | |
% full expansion expands to the cs holding the value | |
\def\forestom#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/\forest@cn/#1}}}\def\forestoget#1#2{\pgfkeysgetvalue{/forest/@node/\forest@cn/#1}{#2}} | |
\def\forestoget#1#2{\pgfkeysgetvalue{/forest/@node/\forest@cn/#1}{#2}} | |
\def\forestolet#1#2{\pgfkeyslet{/forest/@node/\forest@cn/#1}{#2}} | |
\def\forestoset#1#2{\pgfkeyssetvalue{/forest/@node/\forest@cn/#1}{#2}} | |
\def\forestoeset#1#2{% | |
\edef\forest@option@temp{% | |
\noexpand\pgfkeyssetvalue{/forest/@node/\forest@cn/#1}{#2}% | |
}\forest@option@temp | |
} | |
\def\forestoappto#1#2{% | |
\forestoeset{#1}{\forestov{#1}\unexpanded{#2}}% | |
} | |
\def\forestoifdefined#1#2#3{% | |
\pgfkeysifdefined{/forest/@node/\forest@cn/#1}{#2}{#3}% | |
} | |
\let\forestoption\forestov | |
\let\foresteoption\forestove | |
\def\forestOv#1#2{\expandafter\expandafter\expandafter\expandonce | |
\pgfkeysvalueof{/forest/@node/#1/#2}} | |
\def\forestOve#1#2{\pgfkeysvalueof{/forest/@node/#1/#2}} | |
% full expansion expands to the cs holding the value | |
\def\forestOm#1#2{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/#1/#2}}} | |
\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}} | |
\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}} | |
\def\forestOlet#1#2#3{\pgfkeyslet{/forest/@node/#1/#2}{#3}} | |
\def\forestOset#1#2#3{\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}} | |
\def\forestOeset#1#2#3{% | |
\edef\forestoption@temp{% | |
\noexpand\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}% | |
}\forestoption@temp | |
} | |
\def\forestOappto#1#2#3{% | |
\forestOeset{#1}{#2}{\forestOv{#1}{#2}\unexpanded{#3}}% | |
} | |
\def\forestOeappto#1#2#3{% | |
\forestOeset{#1}{#2}{\forestOv{#1}{#2}#3}% | |
} | |
\def\forestOpreto#1#2#3{% | |
\forestOeset{#1}{#2}{\unexpanded{#3}\forestOv{#1}{#2}}% | |
} | |
\def\forestOepreto#1#2#3{% | |
\forestOeset{#1}{#2}{#3\forestOv{#1}{#2}}% | |
} | |
\def\forestOifdefined#1#2#3#4{% | |
\pgfkeysifdefined{/forest/@node/#1/#2}{#3}{#4}% | |
} | |
\def\forestOletO#1#2#3#4{% option #2 of node #1 <-- option #4 of node #3 | |
\forestOget{#3}{#4}\forestoption@temp | |
\forestOlet{#1}{#2}\forestoption@temp} | |
\def\forestOleto#1#2#3{% | |
\forestoget{#3}\forestoption@temp | |
\forestOlet{#1}{#2}\forestoption@temp} | |
\def\forestoletO#1#2#3{% | |
\forestOget{#2}{#3}\forestoption@temp | |
\forestolet{#1}\forestoption@temp} | |
\def\forestoleto#1#2{% | |
\forestoget{#2}\forestoption@temp | |
\forestolet{#1}\forestoption@temp} | |
\def\forest@node@init{% | |
\forestoset{@parent}{0}% | |
\forestoset{@previous}{0}% previous sibling | |
\forestoset{@next}{0}% next sibling | |
\forestoset{@first}{0}% primary child | |
\forestoset{@last}{0}% last child | |
} | |
\def\forestoinit#1{% | |
\pgfkeysgetvalue{/forest/#1}\forestoinit@temp | |
\forestolet{#1}\forestoinit@temp | |
} | |
\newcount\forest@node@maxid | |
\def\forest@node@new#1{% #1 = cs receiving the new node id | |
\advance\forest@node@maxid1 | |
\forest@fornode{\the\forest@node@maxid}{% | |
\forest@node@init | |
\forest@node@setname{node@\forest@cn}% | |
\forest@initializefromstandardnode | |
\edef#1{\forest@cn}% | |
}% | |
} | |
\let\forestoinit@orig\forestoinit | |
\def\forest@node@copy#1#2{% #1=from node id, cs receiving the new node id | |
\advance\forest@node@maxid1 | |
\def\forestoinit##1{\forestoletO{##1}{#1}{##1}}% | |
\forest@fornode{\the\forest@node@maxid}{% | |
\forest@node@init | |
\forest@node@setname{\forest@copy@name@template{\forestOve{#1}{name}}}% | |
\edef#2{\forest@cn}% | |
}% | |
\let\forestoinit\forestoinit@orig | |
} | |
\forestset{ | |
copy name template/.code={\def\forest@copy@name@template##1{#1}}, | |
copy name template/.default={node@\the\forest@node@maxid}, | |
copy name template | |
} | |
\def\forest@tree@copy#1#2{% #1=from node id, #2=cs receiving the new node id | |
\forest@node@copy{#1}\forest@node@copy@temp@id | |
\forest@fornode{\forest@node@copy@temp@id}{% | |
\expandafter\forest@tree@copy@\expandafter{\forest@node@copy@temp@id}{#1}% | |
\edef#2{\forest@cn}% | |
}% | |
} | |
\def\forest@tree@copy@#1#2{% | |
\forest@node@Foreachchild{#2}{% | |
\expandafter\forest@tree@copy\expandafter{\forest@cn}\forest@node@copy@temp@childid | |
\forest@node@Append{#1}{\forest@node@copy@temp@childid}% | |
}% | |
} | |
\def\forest@cn{0} | |
\forest@node@init | |
\def\forest@node@append#1{\expandtwonumberargs\forest@node@Append{\forest@cn}{#1}} | |
\def\forest@node@prepend#1{\expandtwonumberargs\forest@node@Insertafter{\forest@cn}{#1}{0}} | |
\def\forest@node@insertafter#1#2{% | |
\expandthreenumberargs\forest@node@Insertafter{\forest@cn}{#1}{#2}} | |
\def\forest@node@insertbefore#1#2{% | |
\expandthreenumberargs\forest@node@Insertafter{\forest@cn}{#1}{\forestOve{#2}{@previous}}% | |
} | |
\def\forest@node@remove{\expandnumberarg\forest@node@Remove{\forest@cn}} | |
\def\forest@node@Append#1#2{\expandtwonumberargs\forest@node@Append@{#1}{#2}} | |
\def\forest@node@Prepend#1#2{\expandtwonumberargs\forest@node@Insertafter{#1}{#2}{0}} | |
\def\forest@node@Insertafter#1#2#3{% #2 is inserted after #3 | |
\expandthreenumberargs\forest@node@Insertafter@{#1}{#2}{#3}% | |
} | |
\def\forest@node@Insertbefore#1#2#3{% #2 is inserted before #3 | |
\expandthreenumberargs\forest@node@Insertafter{#1}{#2}{\forestOve{#3}{@previous}}% | |
} | |
\def\forest@node@Remove#1{\expandnumberarg\forest@node@Remove@{#1}} | |
\def\forest@node@Insertafter@#1#2#3{% | |
\ifnum\forestOve{#2}{@parent}=0 | |
\else | |
\PackageError{forest}{Insertafter(#1,#2,#3): | |
node #2 already has a parent (\forestOve{#2}{@parent})}{}% | |
\fi | |
\ifnum#3=0 | |
\else | |
\ifnum#1=\forestOve{#3}{@parent} | |
\else | |
\PackageError{forest}{Insertafter(#1,#2,#3): node #1 is not the parent of the | |
intended sibling #3 (with parent \forestOve{#3}{@parent})}{}% | |
\fi | |
\fi | |
\forestOeset{#2}{@parent}{#1}% | |
\forestOeset{#2}{@previous}{#3}% | |
\ifnum#3=0 | |
\forestOget{#1}{@first}\forest@node@temp | |
\forestOeset{#1}{@first}{#2}% | |
\else | |
\forestOget{#3}{@next}\forest@node@temp | |
\forestOeset{#3}{@next}{#2}% | |
\fi | |
\forestOeset{#2}{@next}{\forest@node@temp}% | |
\ifnum\forest@node@temp=0 | |
\forestOeset{#1}{@last}{#2}% | |
\else | |
\forestOeset{\forest@node@temp}{@previous}{#2}% | |
\fi | |
} | |
\def\forest@node@Append@#1#2{% | |
\ifnum\forestOve{#2}{@parent}=0 | |
\else | |
\PackageError{forest}{Append(#1,#2): | |
node #2 already has a parent (\forestOve{#2}{@parent})}{}% | |
\fi | |
\forestOeset{#2}{@parent}{#1}% | |
\forestOget{#1}{@last}\forest@node@temp | |
\forestOeset{#1}{@last}{#2}% | |
\forestOeset{#2}{@previous}{\forest@node@temp}% | |
\ifnum\forest@node@temp=0 | |
\forestOeset{#1}{@first}{#2}% | |
\else | |
\forestOeset{\forest@node@temp}{@next}{#2}% | |
\fi | |
} | |
\def\forest@node@Remove@#1{% | |
\forestOget{#1}{@parent}\forest@node@temp@parent | |
\ifnum\forest@node@temp@parent=0 | |
\else | |
\forestOget{#1}{@previous}\forest@node@temp@previous | |
\forestOget{#1}{@next}\forest@node@temp@next | |
\ifnum\forest@node@temp@previous=0 | |
\forestOeset{\forest@node@temp@parent}{@first}{\forest@node@temp@next}% | |
\else | |
\forestOeset{\forest@node@temp@previous}{@next}{\forest@node@temp@next}% | |
\fi | |
\ifnum\forest@node@temp@next=0 | |
\forestOeset{\forest@node@temp@parent}{@last}{\forest@node@temp@previous}% | |
\else | |
\forestOeset{\forest@node@temp@next}{@previous}{\forest@node@temp@previous}% | |
\fi | |
\forestOset{#1}{@parent}{0}% | |
\forestOset{#1}{@previous}{0}% | |
\forestOset{#1}{@next}{0}% | |
\fi | |
} | |
\def\forest@forthis#1{% | |
\edef\forest@node@marshal{\unexpanded{#1}\def\noexpand\forest@cn}% | |
\expandafter\forest@node@marshal\expandafter{\forest@cn}% | |
} | |
\def\forest@fornode#1#2{% | |
\edef\forest@node@marshal{\edef\noexpand\forest@cn{#1}\unexpanded{#2}\def\noexpand\forest@cn}% | |
\expandafter\forest@node@marshal\expandafter{\forest@cn}% | |
} | |
\def\forest@fornode@ifexists#1#2{% | |
\edef\forest@node@temp{#1}% | |
\ifnum\forest@node@temp=0 | |
\else | |
\@escapeif{\expandnumberarg\forest@fornode{\forest@node@temp}{#2}}% | |
\fi | |
} | |
\def\forest@node@foreachchild#1{\forest@node@Foreachchild{\forest@cn}{#1}} | |
\def\forest@node@Foreachchild#1#2{% | |
\forest@fornode{\forestOve{#1}{@first}}{\forest@node@@forselfandfollowingsiblings{#2}}% | |
} | |
\def\forest@node@@forselfandfollowingsiblings#1{% | |
\ifnum\forest@cn=0 | |
\else | |
\forest@forthis{#1}% | |
\@escapeif{% | |
\edef\forest@cn{\forestove{@next}}% | |
\forest@node@@forselfandfollowingsiblings{#1}% | |
}% | |
\fi | |
} | |
\def\forest@node@foreach#1{\forest@node@Foreach{\forest@cn}{#1}} | |
\def\forest@node@Foreach#1#2{% | |
\forest@fornode{#1}{\forest@node@@foreach{#2}}% | |
} | |
\def\forest@node@@foreach#1{% | |
\forest@forthis{#1}% | |
\ifnum\forestove{@first}=0 | |
\else\@escapeif{% | |
\edef\forest@cn{\forestove{@first}}% | |
\forest@node@@forselfandfollowingsiblings{\forest@node@@foreach{#1}}% | |
}% | |
\fi | |
} | |
\def\forest@node@foreachdescendant#1{\forest@node@Foreachdescendant{\forest@cn}{#1}} | |
\def\forest@node@Foreachdescendant#1#2{% | |
\forest@node@Foreachchild{#1}{% | |
\forest@node@foreach{#2}% | |
}% | |
} | |
\def\forest@node@Compute@numeric@ts@info@#1{% | |
\forest@node@Foreach{#1}{\forest@node@@compute@numeric@ts@info}% | |
\ifnum\forestOve{#1}{@parent}=0 | |
\else | |
\fornode{#1}{\forest@node@@compute@numeric@ts@info@nbar}% | |
\fi | |
\forest@node@Foreachdescendant{#1}{\forest@node@@compute@numeric@ts@info@nbar}% | |
} | |
\def\forest@node@@compute@numeric@ts@info{% | |
\forestoset{n children}{0}% | |
% | |
\edef\forest@node@temp{\forestove{@previous}}% | |
\ifnum\forest@node@temp=0 | |
\forestoset{n}{1}% | |
\else | |
\forestoeset{n}{\number\numexpr\forestOve{\forest@node@temp}{n}+1}% | |
\fi | |
% | |
\edef\forest@node@temp{\forestove{@parent}}% | |
\ifnum\forest@node@temp=0 | |
\forestoset{n}{0}% | |
\forestoset{n'}{0}% | |
\forestoset{level}{0}% | |
\else | |
\forestOeset{\forest@node@temp}{n children}{% | |
\number\numexpr\forestOve{\forest@node@temp}{n children}+1% | |
}% | |
\forestoeset{level}{% | |
\number\numexpr\forestOve{\forest@node@temp}{level}+1% | |
}% | |
\fi | |
} | |
\def\forest@node@@compute@numeric@ts@info@nbar{% | |
\forestoeset{n'}{\number\numexpr\forestOve{\forestove{@parent}}{n children}-\forestove{n}+1}% | |
} | |
\def\forest@node@compute@numeric@ts@info#1{% | |
\expandnumberarg\forest@node@Compute@numeric@ts@info@{\forest@cn}% | |
} | |
\def\forest@node@Compute@numeric@ts@info#1{% | |
\expandnumberarg\forest@node@Compute@numeric@ts@info@{#1}% | |
} | |
\def\forest@node@rootid{% | |
\expandnumberarg\forest@node@Rootid{\forest@cn}% | |
} | |
\def\forest@node@Rootid#1{% #1=node | |
\ifnum\forestOve{#1}{@parent}=0 | |
#1% | |
\else | |
\@escapeif{\expandnumberarg\forest@node@Rootid{\forestOve{#1}{@parent}}}% | |
\fi | |
} | |
\def\forest@node@nthchildid#1{% #1=n | |
\ifnum#1<1 | |
0% | |
\else | |
\expandnumberarg\forest@node@nthchildid@{\number\forestove{@first}}{#1}% | |
\fi | |
} | |
\def\forest@node@nthchildid@#1#2{% | |
\ifnum#1=0 | |
0% | |
\else | |
\ifnum#2>1 | |
\@escapeifif{\expandtwonumberargs | |
\forest@node@nthchildid@{\forestOve{#1}{@next}}{\numexpr#2-1}}% | |
\else | |
#1% | |
\fi | |
\fi | |
} | |
\def\forest@node@nbarthchildid#1{% #1=n | |
\expandnumberarg\forest@node@nbarthchildid@{\number\forestove{@last}}{#1}% | |
} | |
\def\forest@node@nbarthchildid@#1#2{% | |
\ifnum#1=0 | |
0% | |
\else | |
\ifnum#2>1 | |
\@escapeifif{\expandtwonumberargs | |
\forest@node@nbarthchildid@{\forestOve{#1}{@previous}}{\numexpr#2-1}}% | |
\else | |
#1% | |
\fi | |
\fi | |
} | |
\def\forest@node@nornbarthchildid#1{% | |
\ifnum#1>0 | |
\forest@node@nthchildid{#1}% | |
\else | |
\ifnum#1<0 | |
\forest@node@nbarthchildid{-#1}% | |
\else | |
\forest@node@nornbarthchildid@error | |
\fi | |
\fi | |
} | |
\def\forest@node@nornbarthchildid@error{% | |
\PackageError{forest}{In \string\forest@node@nornbarthchildid, n should !=0}{}% | |
} | |
\def\forest@node@previousleafid{% | |
\expandnumberarg\forest@node@Previousleafid{\forest@cn}% | |
} | |
\def\forest@node@Previousleafid#1{% | |
\ifnum\forestOve{#1}{@previous}=0 | |
\@escapeif{\expandnumberarg\forest@node@previousleafid@Goup{#1}}% | |
\else | |
\expandnumberarg\forest@node@previousleafid@Godown{\forestOve{#1}{@previous}}% | |
\fi | |
} | |
\def\forest@node@previousleafid@Goup#1{% | |
\ifnum\forestOve{#1}{@parent}=0 | |
\PackageError{forest}{get previous leaf: this is the first leaf}{}% | |
\else | |
\@escapeif{\expandnumberarg\forest@node@Previousleafid{\forestOve{#1}{@parent}}}% | |
\fi | |
} | |
\def\forest@node@previousleafid@Godown#1{% | |
\ifnum\forestOve{#1}{@last}=0 | |
#1% | |
\else | |
\@escapeif{\expandnumberarg\forest@node@previousleafid@Godown{\forestOve{#1}{@last}}}% | |
\fi | |
} | |
\def\forest@node@nextleafid{% | |
\expandnumberarg\forest@node@Nextleafid{\forest@cn}% | |
} | |
\def\forest@node@Nextleafid#1{% | |
\ifnum\forestOve{#1}{@next}=0 | |
\@escapeif{\expandnumberarg\forest@node@nextleafid@Goup{#1}}% | |
\else | |
\expandnumberarg\forest@node@nextleafid@Godown{\forestOve{#1}{@next}}% | |
\fi | |
} | |
\def\forest@node@nextleafid@Goup#1{% | |
\ifnum\forestOve{#1}{@parent}=0 | |
\PackageError{forest}{get next leaf: this is the last leaf}{}% | |
\else | |
\@escapeif{\expandnumberarg\forest@node@Nextleafid{\forestOve{#1}{@parent}}}% | |
\fi | |
} | |
\def\forest@node@nextleafid@Godown#1{% | |
\ifnum\forestOve{#1}{@first}=0 | |
#1% | |
\else | |
\@escapeif{\expandnumberarg\forest@node@nextleafid@Godown{\forestOve{#1}{@first}}}% | |
\fi | |
} | |
\def\forest@node@linearnextid{% | |
\ifnum\forestove{@first}=0 | |
\expandafter\forest@node@linearnextnotdescendantid | |
\else | |
\forestove{@first}% | |
\fi | |
} | |
\def\forest@node@linearnextnotdescendantid{% | |
\expandnumberarg\forest@node@Linearnextnotdescendantid{\forest@cn}% | |
} | |
\def\forest@node@Linearnextnotdescendantid#1{% | |
\ifnum\forestOve{#1}{@next}=0 | |
\@escapeif{\expandnumberarg\forest@node@Linearnextnotdescendantid{\forestOve{#1}{@parent}}}% | |
\else | |
\forestOve{#1}{@next}% | |
\fi | |
} | |
\def\forest@node@linearpreviousid{% | |
\ifnum\forestove{@previous}=0 | |
\forestove{@parent}% | |
\else | |
\forest@node@previousleafid | |
\fi | |
} | |
\def\forest@ifancestorof#1{% is the current node an ancestor of #1? Yes: #2, no: #3 | |
\expandnumberarg\forest@ifancestorof@{\forestOve{#1}{@parent}}% | |
} | |
\def\forest@ifancestorof@#1#2#3{% | |
\ifnum#1=0 | |
\def\forest@ifancestorof@next{\@secondoftwo}% | |
\else | |
\ifnum\forest@cn=#1 | |
\def\forest@ifancestorof@next{\@firstoftwo}% | |
\else | |
\def\forest@ifancestorof@next{\expandnumberarg\forest@ifancestorof@{\forestOve{#1}{@parent}}}% | |
\fi | |
\fi | |
\forest@ifancestorof@next{#2}{#3}% | |
} | |
\newloop\forest@nodewalk@loop | |
\forestset{ | |
@handlers@save@currentpath/.code={% | |
\edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}% | |
\let\forest@currentkey\pgfkeyscurrentkey | |
\pgfkeys@split@path | |
\edef\forest@currentpath{\pgfkeyscurrentpath}% | |
\let\forest@currentname\pgfkeyscurrentname | |
}, | |
/handlers/.step 0 args/.style={ | |
/forest/@handlers@save@currentpath, | |
\forest@currentkey/.code={#1\forestset{node walk/every step}}, | |
/forest/for \forest@currentname/.style/.expanded={% | |
for={\forest@currentname}{####1}% | |
} | |
}, | |
/handlers/.step 1 arg/.style={% | |
/forest/@handlers@save@currentpath, | |
\forest@currentkey/.code={#1\forestset{node walk/every step}}, | |
/forest/for \forest@currentname/.style 2 args/.expanded={% | |
for={\forest@currentname=####1}{####2}% | |
} | |
}, | |
node walk/.code={% | |
\forestset{% | |
node walk/before walk,% | |
node walk/.cd, | |
#1,% | |
/forest/.cd, | |
node walk/after walk | |
}% | |
}, | |
for/.code 2 args={% | |
\forest@forthis{% | |
\pgfkeysalso{% | |
node walk/before walk/.style={},% | |
node walk/every step/.style={},% | |
node walk/after walk/.style={/forest,if id=0{}{#2}},% | |
%node walk/after walk/.style={#2},% | |
node walk={#1}% | |
}% | |
}% | |
}, | |
node walk/.cd, | |
before walk/.code={}, | |
every step/.code={}, | |
after walk/.code={}, | |
current/.step 0 args={}, | |
current/.default=1, | |
next/.step 0 args={\edef\forest@cn{\forestove{@next}}}, | |
next/.default=1, | |
previous/.step 0 args={\edef\forest@cn{\forestove{@previous}}}, | |
previous/.default=1, | |
parent/.step 0 args={\edef\forest@cn{\forestove{@parent}}}, | |
parent/.default=1, | |
first/.step 0 args={\edef\forest@cn{\forestove{@first}}}, | |
first/.default=1, | |
last/.step 0 args={\edef\forest@cn{\forestove{@last}}}, | |
last/.default=1, | |
n/.step 1 arg={% | |
\def\forest@nodewalk@temp{#1}% | |
\ifx\forest@nodewalk@temp\pgfkeysnovalue@text | |
\edef\forest@cn{\forestove{@next}}% | |
\else | |
\edef\forest@cn{\forest@node@nthchildid{#1}}% | |
\fi | |
}, | |
n'/.step 1 arg={\edef\forest@cn{\forest@node@nbarthchildid{#1}}}, | |
sibling/.step 0 args={% | |
\edef\forest@cn{% | |
\ifnum\forestove{@previous}=0 | |
\forestove{@next}% | |
\else | |
\forestove{@previous}% | |
\fi | |
}% | |
}, | |
previous leaf/.step 0 args={\edef\forest@cn{\forest@node@previousleafid}}, | |
previous leaf/.default=1, | |
next leaf/.step 0 args={\edef\forest@cn{\forest@node@nextleafid}}, | |
next leaf/.default=1, | |
linear next/.step 0 args={\edef\forest@cn{\forest@node@linearnextid}}, | |
linear previous/.step 0 args={\edef\forest@cn{\forest@node@linearpreviousid}}, | |
first leaf/.step 0 args={% | |
\forest@nodewalk@loop | |
\edef\forest@cn{\forestove{@first}}% | |
\unless\ifnum\forestove{@first}=0 | |
\forest@nodewalk@repeat | |
}, | |
last leaf/.step 0 args={% | |
\forest@nodewalk@loop | |
\edef\forest@cn{\forestove{@last}}% | |
\unless\ifnum\forestove{@last}=0 | |
\forest@nodewalk@repeat | |
}, | |
to tier/.step 1 arg={% | |
\def\forest@nodewalk@giventier{#1}% | |
\forest@nodewalk@loop | |
\forestoget{tier}\forest@nodewalk@tier | |
\unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier | |
\forestoget{@parent}\forest@cn | |
\forest@nodewalk@repeat | |
}, | |
next on tier/.step 0 args={\forest@nodewalk@nextontier}, | |
next on tier/.default=1, | |
previous on tier/.step 0 args={\forest@nodewalk@previousontier}, | |
previous on tier/.default=1, | |
name/.step 1 arg={\edef\forest@cn{\forest@node@Nametoid{#1}}}, | |
root/.step 0 args={\edef\forest@cn{\forest@node@rootid}}, | |
root'/.step 0 args={\edef\forest@cn{\forest@root}}, | |
id/.step 1 arg={\edef\forest@cn{#1}}, | |
% maybe it's not wise to have short-step sequences and names potentially clashing | |
% .unknown/.code={% | |
% \forest@node@Ifnamedefined{\pgfkeyscurrentname}% | |
% {\pgfkeysalso{name=\pgfkeyscurrentname}}% | |
% {\expandafter\forest@nodewalk@shortsteps\pgfkeyscurrentname\forest@nodewalk@endshortsteps}% | |
% }, | |
.unknown/.code={% | |
\expandafter\forest@nodewalk@shortsteps\pgfkeyscurrentname\forest@nodewalk@endshortsteps | |
}, | |
node walk/.style={/forest/node walk={#1}}, | |
trip/.code={\forest@forthis{\pgfkeysalso{#1}}}, | |
group/.code={\forest@go{#1}\forestset{node walk/every step}}, | |
% repeat is taken later from /forest/repeat | |
p/.style={previous=1}, | |
%n/.style={next=1}, % defined in "long" n | |
u/.style={parent=1}, | |
s/.style={sibling}, | |
c/.style={current=1}, | |
r/.style={root}, | |
P/.style={previous leaf=1}, | |
N/.style={next leaf=1}, | |
F/.style={first leaf=1}, | |
L/.style={last leaf=1}, | |
>/.style={next on tier=1}, | |
</.style={previous on tier=1}, | |
1/.style={n=1}, | |
2/.style={n=2}, | |
3/.style={n=3}, | |
4/.style={n=4}, | |
5/.style={n=5}, | |
6/.style={n=6}, | |
7/.style={n=7}, | |
8/.style={n=8}, | |
9/.style={n=9}, | |
l/.style={last=1}, | |
%{...} is short for group={...} | |
} | |
\def\forest@nodewalk@nextontier{% | |
\forestoget{tier}\forest@nodewalk@giventier | |
\edef\forest@cn{\forest@node@linearnextnotdescendantid}% | |
\forest@nodewalk@loop | |
\forestoget{tier}\forest@nodewalk@tier | |
\unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier | |
\edef\forest@cn{\forest@node@linearnextid}% | |
\forest@nodewalk@repeat | |
} | |
\def\forest@nodewalk@previousontier{% | |
\forestoget{tier}\forest@nodewalk@giventier | |
\forest@nodewalk@loop | |
\edef\forest@cn{\forest@node@linearpreviousid}% | |
\forestoget{tier}\forest@nodewalk@tier | |
\unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier | |
\forest@nodewalk@repeat | |
} | |
\def\forest@nodewalk@shortsteps{% | |
\futurelet\forest@nodewalk@nexttoken\forest@nodewalk@shortsteps@ | |
} | |
\def\forest@nodewalk@shortsteps@#1{% | |
\ifx\forest@nodewalk@nexttoken\forest@nodewalk@endshortsteps | |
\else | |
\ifx\forest@nodewalk@nexttoken\bgroup | |
\pgfkeysalso{group=#1}% | |
\@escapeifif\forest@nodewalk@shortsteps | |
\else | |
\pgfkeysalso{#1}% | |
\@escapeifif\forest@nodewalk@shortsteps | |
\fi | |
\fi | |
} | |
\def\forest@go#1{% | |
{% | |
\forestset{% | |
node walk/before walk/.code={},% | |
node walk/every step/.code={},% | |
node walk/after walk/.code={},% | |
node walk={#1}% | |
}% | |
\expandafter | |
}% | |
\expandafter\def\expandafter\forest@cn\expandafter{\forest@cn}% | |
} | |
\def\forest@declarehandler#1#2#3{%#1=handler for specific type,#2=option name,#3=default value | |
\pgfkeyssetvalue{/forest/#2}{#3}% | |
\appto\forest@node@init{\forestoinit{#2}}% | |
\forest@convert@others@to@underscores{#2}\forest@pgfmathoptionname | |
\edef\forest@marshal{% | |
\noexpand#1{/forest/#2}{/forest}{#2}{\forest@pgfmathoptionname}% | |
}\forest@marshal | |
} | |
\def\forest@def@with@pgfeov#1#2{% \pgfeov mustn't occur in the arg of the .code handler!!! | |
\long\def#1##1\pgfeov{#2}% | |
} | |
\newtoks\forest@temp@toks | |
\def\forest@declaretoks@handler#1#2#3#4{% | |
\forest@declaretoks@handler@A{#1}{#2}{#3}{#4}{}% | |
} | |
\def\forest@declarekeylist@handler#1#2#3#4{% | |
\forest@declaretoks@handler@A{#1}{#2}{#3}{#4}{,}% | |
\pgfkeysgetvalue{#1/.@cmd}\forest@temp | |
\pgfkeyslet{#1'/.@cmd}\forest@temp | |
\pgfkeyssetvalue{#1'/option@name}{#3}% | |
\pgfkeysgetvalue{#1+/.@cmd}\forest@temp | |
\pgfkeyslet{#1/.@cmd}\forest@temp | |
} | |
\def\forest@declaretoks@handler@A#1#2#3#4#5{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix | |
\pgfkeysalso{% | |
#1/.code={\forestOset{\forest@setter@node}{#3}{##1}}, | |
#1+/.code={\forestOappto{\forest@setter@node}{#3}{#5##1}}, | |
#1-/.code={\forestOpreto{\forest@setter@node}{#3}{##1#5}}, | |
#2/if #3/.code n args={3}{% | |
\forestoget{#3}\forest@temp@option@value | |
\edef\forest@temp@compared@value{\unexpanded{##1}}% | |
\ifx\forest@temp@option@value\forest@temp@compared@value | |
\pgfkeysalso{##2}% | |
\else | |
\pgfkeysalso{##3}% | |
\fi | |
}, | |
#2/if in #3/.code n args={3}{% | |
\forestoget{#3}\forest@temp@option@value | |
\edef\forest@temp@compared@value{\unexpanded{##1}}% | |
\expandafter\expandafter\expandafter\pgfutil@in@\expandafter\expandafter\expandafter{\expandafter\forest@temp@compared@value\expandafter}\expandafter{\forest@temp@option@value}% | |
\ifpgfutil@in@ | |
\pgfkeysalso{##2}% | |
\else | |
\pgfkeysalso{##3}% | |
\fi | |
}, | |
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, | |
#2/where in #3/.style n args={3}{for tree={#2/if in #3={##1}{##2}{##3}}} | |
}% | |
\pgfkeyssetvalue{#1/option@name}{#3}% | |
\pgfkeyssetvalue{#1+/option@name}{#3}% | |
\pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@toks{##1}{#3}}% | |
} | |
\def\forest@declareautowrappedtoks@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix | |
\forest@declaretoks@handler{#1}{#2}{#3}{#4}% | |
\pgfkeysgetvalue{#1/.@cmd}\forest@temp | |
\pgfkeyslet{#1'/.@cmd}\forest@temp | |
\pgfkeysalso{#1/.style={#1'/.wrap value={##1}}}% | |
\pgfkeyssetvalue{#1'/option@name}{#3}% | |
\pgfkeysgetvalue{#1+/.@cmd}\forest@temp | |
\pgfkeyslet{#1+'/.@cmd}\forest@temp | |
\pgfkeysalso{#1+/.style={#1+'/.wrap value={##1}}}% | |
\pgfkeyssetvalue{#1+'/option@name}{#3}% | |
\pgfkeysgetvalue{#1-/.@cmd}\forest@temp | |
\pgfkeyslet{#1-'/.@cmd}\forest@temp | |
\pgfkeysalso{#1-/.style={#1-'/.wrap value={##1}}}% | |
\pgfkeyssetvalue{#1-'/option@name}{#3}% | |
} | |
\def\forest@declarereadonlydimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname | |
\pgfkeysalso{% | |
#2/if #3/.code n args={3}{% | |
\forestoget{#3}\forest@temp@option@value | |
\ifdim\forest@temp@option@value=##1\relax | |
\pgfkeysalso{##2}% | |
\else | |
\pgfkeysalso{##3}% | |
\fi | |
}, | |
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, | |
}% | |
\pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@dimen{##1}{#3}}% | |
} | |
\def\forest@declaredimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname | |
\forest@declarereadonlydimen@handler{#1}{#2}{#3}{#4}% | |
\pgfkeysalso{% | |
#1/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\forestOlet{\forest@setter@node}{#3}\forest@temp | |
}, | |
#1+/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\pgfutil@tempdima=\forestove{#3} | |
\advance\pgfutil@tempdima\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1-/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\pgfutil@tempdima=\forestove{#3} | |
\advance\pgfutil@tempdima-\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1*/.style={% | |
#1={#4()*(##1)}% | |
}, | |
#1:/.style={% | |
#1={#4()/(##1)}% | |
}, | |
#1'/.code={% | |
\pgfutil@tempdima=##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1'+/.code={% | |
\pgfutil@tempdima=\forestove{#3}\relax | |
\advance\pgfutil@tempdima##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1'-/.code={% | |
\pgfutil@tempdima=\forestove{#3}\relax | |
\advance\pgfutil@tempdima-##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1'*/.style={% | |
\pgfutil@tempdima=\forestove{#3}\relax | |
\multiply\pgfutil@tempdima##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
#1':/.style={% | |
\pgfutil@tempdima=\forestove{#3}\relax | |
\divide\pgfutil@tempdima##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% | |
}, | |
}% | |
\pgfkeyssetvalue{#1/option@name}{#3}% | |
\pgfkeyssetvalue{#1+/option@name}{#3}% | |
\pgfkeyssetvalue{#1-/option@name}{#3}% | |
\pgfkeyssetvalue{#1*/option@name}{#3}% | |
\pgfkeyssetvalue{#1:/option@name}{#3}% | |
\pgfkeyssetvalue{#1'/option@name}{#3}% | |
\pgfkeyssetvalue{#1'+/option@name}{#3}% | |
\pgfkeyssetvalue{#1'-/option@name}{#3}% | |
\pgfkeyssetvalue{#1'*/option@name}{#3}% | |
\pgfkeyssetvalue{#1':/option@name}{#3}% | |
} | |
\def\forest@declarereadonlycount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname | |
\pgfkeysalso{ | |
#2/if #3/.code n args={3}{% | |
\forestoget{#3}\forest@temp@option@value | |
\ifnum\forest@temp@option@value=##1\relax | |
\pgfkeysalso{##2}% | |
\else | |
\pgfkeysalso{##3}% | |
\fi | |
}, | |
#2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, | |
}% | |
\pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@count{##1}{#3}}% | |
} | |
\def\forest@declarecount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname | |
\forest@declarereadonlycount@handler{#1}{#2}{#3}{#4}% | |
\pgfkeysalso{ | |
#1/.code={% | |
\pgfmathtruncatemacro\forest@temp{##1}% | |
\forestOlet{\forest@setter@node}{#3}\forest@temp | |
}, | |
#1+/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\c@pgf@counta=\forestove{#3}\relax | |
\advance\c@pgf@counta\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1-/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\c@pgf@counta=\forestove{#3}\relax | |
\advance\c@pgf@counta-\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1*/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\c@pgf@counta=\forestove{#3}\relax | |
\multiply\c@pgf@counta\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1:/.code={% | |
\pgfmathsetlengthmacro\forest@temp{##1}% | |
\c@pgf@counta=\forestove{#3}\relax | |
\divide\c@pgf@counta\forest@temp\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1'/.code={% | |
\c@pgf@counta=##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1'+/.code={% | |
\c@pgf@counta=\forestove{#3}\relax | |
\advance\c@pgf@counta##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1'-/.code={% | |
\c@pgf@counta=\forestove{#3}\relax | |
\advance\c@pgf@counta-##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1'*/.style={% | |
\c@pgf@counta=\forestove{#3}\relax | |
\multiply\c@pgf@counta##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
#1':/.style={% | |
\c@pgf@counta=\forestove{#3}\relax | |
\divide\c@pgf@counta##1\relax | |
\forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% | |
}, | |
}% | |
\pgfkeyssetvalue{#1/option@name}{#3}% | |
\pgfkeyssetvalue{#1+/option@name}{#3}% | |
\pgfkeyssetvalue{#1-/option@name}{#3}% | |
\pgfkeyssetvalue{#1*/option@name}{#3}% | |
\pgfkeyssetvalue{#1:/option@name}{#3}% | |
\pgfkeyssetvalue{#1'/option@name}{#3}% | |
\pgfkeyssetvalue{#1'+/option@name}{#3}% | |
\pgfkeyssetvalue{#1'-/option@name}{#3}% | |
\pgfkeyssetvalue{#1'*/option@name}{#3}% | |
\pgfkeyssetvalue{#1':/option@name}{#3}% | |
} | |
\def\forest@declareboolean@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname | |
\pgfkeysalso{% | |
#1/.code={% | |
\ifstrequal{##1}{1}{% | |
\forestOset{\forest@setter@node}{#3}{1}% | |
}{% | |
\pgfmathifthenelse{##1}{1}{0}% | |
\forestOlet{\forest@setter@node}{#3}\pgfmathresult | |
}% | |
}, | |
#1/.default=1, | |
#2/not #3/.code={\forestOset{\forest@setter@node}{#3}{0}}, | |
#2/if #3/.code 2 args={% | |
\forestoget{#3}\forest@temp@option@value | |
\ifnum\forest@temp@option@value=1 | |
\pgfkeysalso{##1}% | |
\else | |
\pgfkeysalso{##2}% | |
\fi | |
}, | |
#2/where #3/.style 2 args={for tree={#2/if #3={##1}{##2}}} | |
}% | |
\pgfkeyssetvalue{#1/option@name}{#3}% | |
\pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@count{##1}{#3}}% | |
} | |
\pgfkeys{/forest, | |
declare toks/.code 2 args={% | |
\forest@declarehandler\forest@declaretoks@handler{#1}{#2}% | |
}, | |
declare autowrapped toks/.code 2 args={% | |
\forest@declarehandler\forest@declareautowrappedtoks@handler{#1}{#2}% | |
}, | |
declare keylist/.code 2 args={% | |
\forest@declarehandler\forest@declarekeylist@handler{#1}{#2}% | |
}, | |
declare readonly dimen/.code={% | |
\forest@declarehandler\forest@declarereadonlydimen@handler{#1}{}% | |
}, | |
declare dimen/.code 2 args={% | |
\forest@declarehandler\forest@declaredimen@handler{#1}{#2}% | |
}, | |
declare readonly count/.code={% | |
\forest@declarehandler\forest@declarereadonlycount@handler{#1}{}% | |
}, | |
declare count/.code 2 args={% | |
\forest@declarehandler\forest@declarecount@handler{#1}{#2}% | |
}, | |
declare boolean/.code 2 args={% | |
\forest@declarehandler\forest@declareboolean@handler{#1}{#2}% | |
}, | |
/handlers/.pgfmath/.code={% | |
\pgfmathparse{#1}% | |
\pgfkeysalso{\pgfkeyscurrentpath/.expand once=\pgfmathresult}% | |
}, | |
/handlers/.wrap value/.code={% | |
\edef\forest@handlers@wrap@currentpath{\pgfkeyscurrentpath}% | |
\pgfkeysgetvalue{\forest@handlers@wrap@currentpath/option@name}\forest@currentoptionname | |
\expandafter\forestoget\expandafter{\forest@currentoptionname}\forest@option@value | |
\forest@def@with@pgfeov\forest@wrap@code{#1}% | |
\expandafter\edef\expandafter\forest@wrapped@value\expandafter{\expandafter\expandonce\expandafter{\expandafter\forest@wrap@code\forest@option@value\pgfeov}}% | |
\pgfkeysalso{\forest@handlers@wrap@currentpath/.expand once=\forest@wrapped@value}% | |
}, | |
/handlers/.wrap pgfmath arg/.code 2 args={% | |
\pgfmathparse{#2}\let\forest@wrap@arg@i\pgfmathresult | |
\edef\forest@wrap@args{{\expandonce\forest@wrap@arg@i}}% | |
\def\forest@wrap@code##1{#1}% | |
\expandafter\expandafter\expandafter\forest@temp@toks\expandafter\expandafter\expandafter{\expandafter\forest@wrap@code\forest@wrap@args}% | |
\pgfkeysalso{\pgfkeyscurrentpath/.expand once=\the\forest@temp@toks}% | |
}, | |
/handlers/.wrap 2 pgfmath args/.code n args={3}{% | |
\pgfmathparse{#2}\let\forest@wrap@arg@i\pgfmathresult | |
\pgfmathparse{#3}\let\forest@wrap@arg@ii\pgfmathresult | |
\edef\forest@wrap@args{{\expandonce\forest@wrap@arg@i}{\expandonce\forest@wrap@arg@ii}}% | |
\def\forest@wrap@code##1##2{#1}% | |
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\forest@wrapped\expandafter\expandafter\expandafter{\expandafter\forest@wrap@code\forest@wrap@args}% | |
\pgfkeysalso{\pgfkeyscurrentpath/.expand once=\forest@wrapped}% | |
}, | |
/handlers/.wrap 3 pgfmath args/.code n args={4}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{}{}{}{}{}{3}% | |
\forest@wrap@n@pgfmath@do{#1}{3}}, | |
/handlers/.wrap 4 pgfmath args/.code n args={5}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{}{}{}{}{4}% | |
\forest@wrap@n@pgfmath@do{#1}{4}}, | |
/handlers/.wrap 5 pgfmath args/.code n args={6}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{}{}{}{5}% | |
\forest@wrap@n@pgfmath@do{#1}{5}}, | |
/handlers/.wrap 6 pgfmath args/.code n args={7}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{}{}{6}% | |
\forest@wrap@n@pgfmath@do{#1}{6}}, | |
/handlers/.wrap 7 pgfmath args/.code n args={8}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{}{7}% | |
\forest@wrap@n@pgfmath@do{#1}{7}}, | |
/handlers/.wrap 8 pgfmath args/.code n args={9}{% | |
\forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}{8}% | |
\forest@wrap@n@pgfmath@do{#1}{8}}, | |
} | |
\def\forest@wrap@n@pgfmath@args#1#2#3#4#5#6#7#8#9{% | |
\pgfmathparse{#1}\let\forest@wrap@arg@i\pgfmathresult | |
\ifnum#9>1 \pgfmathparse{#2}\let\forest@wrap@arg@ii\pgfmathresult\fi | |
\ifnum#9>2 \pgfmathparse{#3}\let\forest@wrap@arg@iii\pgfmathresult\fi | |
\ifnum#9>3 \pgfmathparse{#4}\let\forest@wrap@arg@iv\pgfmathresult\fi | |
\ifnum#9>4 \pgfmathparse{#5}\let\forest@wrap@arg@v\pgfmathresult\fi | |
\ifnum#9>5 \pgfmathparse{#6}\let\forest@wrap@arg@vi\pgfmathresult\fi | |
\ifnum#9>6 \pgfmathparse{#7}\let\forest@wrap@arg@vii\pgfmathresult\fi | |
\ifnum#9>7 \pgfmathparse{#8}\let\forest@wrap@arg@viii\pgfmathresult\fi | |
\edef\forest@wrap@args{% | |
{\expandonce\forest@wrap@arg@i} | |
\ifnum#9>1 {\expandonce\forest@wrap@arg@ii}\fi | |
\ifnum#9>2 {\expandonce\forest@wrap@arg@iii}\fi | |
\ifnum#9>3 {\expandonce\forest@wrap@arg@iv}\fi | |
\ifnum#9>4 {\expandonce\forest@wrap@arg@v}\fi | |
\ifnum#9>5 {\expandonce\forest@wrap@arg@vi}\fi | |
\ifnum#9>6 {\expandonce\forest@wrap@arg@vii}\fi | |
\ifnum#9>7 {\expandonce\forest@wrap@arg@viii}\fi | |
}% | |
} | |
\def\forest@wrap@n@pgfmath@do#1#2{% | |
\ifcase#2\relax | |
\or\def\forest@wrap@code##1{#1}% | |
\or\def\forest@wrap@code##1##2{#1}% | |
\or\def\forest@wrap@code##1##2##3{#1}% | |
\or\def\forest@wrap@code##1##2##3##4{#1}% | |
\or\def\forest@wrap@code##1##2##3##4##5{#1}% | |
\or\def\forest@wrap@code##1##2##3##4##5##6{#1}% | |
\or\def\forest@wrap@code##1##2##3##4##5##6##7{#1}% | |
\or\def\forest@wrap@code##1##2##3##4##5##6##7##8{#1}% | |
\fi | |
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\forest@wrapped\expandafter\expandafter\expandafter{\expandafter\forest@wrap@code\forest@wrap@args}% | |
\pgfkeysalso{\pgfkeyscurrentpath/.expand once=\forest@wrapped}% | |
} | |
\def\forest@node@setname#1{% | |
\forestoeset{name}{#1}% | |
\csedef{forest@id@of@#1}{\forest@cn}% | |
} | |
\def\forest@node@Nametoid#1{% #1 = name | |
\csname forest@id@of@#1\endcsname | |
} | |
\def\forest@node@Ifnamedefined#1{% #1 = name, #2=true,#3=false | |
\ifcsname forest@id@of@#1\endcsname | |
\expandafter\@firstoftwo | |
\else | |
\expandafter\@secondoftwo | |
\fi | |
} | |
\def\forest@node@setalias#1{% | |
\csedef{forest@id@of@#1}{\forest@cn}% | |
} | |
\def\forest@node@Setalias#1#2{% | |
\csedef{forest@id@of@#2}{#1}% | |
} | |
\forestset{ | |
TeX/.code={#1}, | |
TeX'/.code={\appto\forest@externalize@loadimages{#1}#1}, | |
TeX''/.code={\appto\forest@externalize@loadimages{#1}}, | |
declare toks={name}{}, | |
name/.code={% override the default setter | |
\forest@node@setname{#1}% | |
}, | |
alias/.code={\forest@node@setalias{#1}}, | |
begin draw/.code={\begin{tikzpicture}}, | |
end draw/.code={\end{tikzpicture}}, | |
begin forest/.code={}, | |
end forest/.code={}, | |
declare autowrapped toks={content}{}, | |
declare count={grow}{270}, | |
TeX={% a hack for grow-reversed connection, and compass-based grow specification | |
\pgfkeysgetvalue{/forest/grow/.@cmd}\forest@temp | |
\pgfkeyslet{/forest/grow@@/.@cmd}\forest@temp | |
}, | |
grow/.style={grow@={#1},reversed=0}, | |
grow'/.style={grow@={#1},reversed=1}, | |
grow''/.style={grow@={#1}}, | |
grow@/.is choice, | |
grow@/east/.style={/forest/grow@@=0}, | |
grow@/north east/.style={/forest/grow@@=45}, | |
grow@/north/.style={/forest/grow@@=90}, | |
grow@/north west/.style={/forest/grow@@=135}, | |
grow@/west/.style={/forest/grow@@=180}, | |
grow@/south west/.style={/forest/grow@@=225}, | |
grow@/south/.style={/forest/grow@@=270}, | |
grow@/south east/.style={/forest/grow@@=315}, | |
grow@/.unknown/.code={\let\forest@temp@grow\pgfkeyscurrentname | |
\pgfkeysalso{/forest/grow@@/.expand once=\forest@temp@grow}}, | |
declare boolean={reversed}{0}, | |
declare toks={parent anchor}{}, | |
declare toks={child anchor}{}, | |
declare toks={anchor}{base}, | |
declare toks={calign}{midpoint}, | |
TeX={% | |
\pgfkeysgetvalue{/forest/calign/.@cmd}\forest@temp | |
\pgfkeyslet{/forest/calign'/.@cmd}\forest@temp | |
}, | |
calign/.is choice, | |
calign/child/.style={calign'=child}, | |
calign/first/.style={calign'=child,calign primary child=1}, | |
calign/last/.style={calign'=child,calign primary child=-1}, | |
calign with current/.style={for parent/.wrap pgfmath arg={calign=child,calign primary child=##1}{n}}, | |
calign with current edge/.style={for parent/.wrap pgfmath arg={calign=child edge,calign primary child=##1}{n}}, | |
calign/child edge/.style={calign'=child edge}, | |
calign/midpoint/.style={calign'=midpoint}, | |
calign/center/.style={calign'=midpoint,calign primary child=1,calign secondary child=-1}, | |
calign/edge midpoint/.style={calign'=edge midpoint}, | |
calign/fixed angles/.style={calign'=fixed angles}, | |
calign/fixed edge angles/.style={calign'=fixed edge angles}, | |
calign/.unknown/.code={\PackageError{forest}{unknown calign '\pgfkeyscurrentname'}{}}, | |
declare count={calign primary child}{1}, | |
declare count={calign secondary child}{-1}, | |
declare count={calign primary angle}{-35}, | |
declare count={calign secondary angle}{35}, | |
calign child/.style={calign primary child={#1}}, | |
calign angle/.style={calign primary angle={-#1},calign secondary angle={#1}}, | |
declare toks={tier}{}, | |
declare toks={fit}{tight}, | |
declare boolean={ignore}{0}, | |
declare boolean={ignore edge}{0}, | |
no edge/.style={edge'={},ignore edge}, | |
declare keylist={edge}{draw}, | |
declare toks={edge path}{% | |
\noexpand\path[\forestoption{edge}]% | |
(\forestOve{\forestove{@parent}}{name}.parent anchor)--(\forestove{name}.child anchor)\forestoption{edge label};}, | |
triangle/.style={edge path={% | |
\noexpand\path[\forestoption{edge}]% | |
(\forestove{name}.north east)--(\forestOve{\forestove{@parent}}{name}.south)--(\forestove{name}.north west)--(\forestove{name}.north east)\forestoption{edge label};}}, | |
declare toks={edge label}{}, | |
declare boolean={phantom}{0}, | |
baseline/.style={alias={forest@baseline@node}}, | |
declare readonly count={n}, | |
declare readonly count={n'}, | |
declare readonly count={n children}, | |
declare readonly count={level}, | |
declare dimen=x{}, | |
declare dimen=y{}, | |
declare dimen={s}{0pt}, | |
declare dimen={l}{6ex}, % just in case: should be set by the calibration | |
declare dimen={s sep}{0.6666em}, | |
declare dimen={l sep}{1ex}, % just in case: calibration! | |
declare keylist={node options}{}, | |
declare toks={tikz}{}, | |
afterthought/.style={tikz+={#1}}, | |
label/.style={tikz={\path[late options={% | |
name=\forestoption{name},label={#1}}];}}, | |
pin/.style={tikz={\path[late options={% | |
name=\forestoption{name},pin={#1}}];}}, | |
declare toks={content format}{\forestoption{content}}, | |
math content/.style={content format={\ensuremath{\forestoption{content}}}}, | |
declare toks={node format}{% | |
\noexpand\node | |
[\forestoption{node options},anchor=\forestoption{anchor}]% | |
(\forestoption{name})% | |
{\foresteoption{content format}};% | |
}, | |
tabular@environment/.style={content format={% | |
\noexpand\begin{tabular}[\forestoption{base}]{\forestoption{align}}% | |
\forestoption{content}% | |
\noexpand\end{tabular}% | |
}}, | |
declare toks={align}{}, | |
TeX={\pgfkeysgetvalue{/forest/align/.@cmd}\forest@temp | |
\pgfkeyslet{/forest/align'/.@cmd}\forest@temp}, | |
align/.is choice, | |
align/.unknown/.code={% | |
\edef\forest@marshal{% | |
\noexpand\pgfkeysalso{% | |
align'={\pgfkeyscurrentname},% | |
tabular@environment | |
}% | |
}\forest@marshal | |
}, | |
align/center/.style={align'={@{}c@{}},tabular@environment}, | |
align/left/.style={align'={@{}l@{}},tabular@environment}, | |
align/right/.style={align'={@{}r@{}},tabular@environment}, | |
declare toks={base}{t}, | |
TeX={\pgfkeysgetvalue{/forest/base/.@cmd}\forest@temp | |
\pgfkeyslet{/forest/base'/.@cmd}\forest@temp}, | |
base/.is choice, | |
base/top/.style={base'=t}, | |
base/bottom/.style={base'=b}, | |
base/.unknown/.style={base'/.expand once=\pgfkeyscurrentname}, | |
.unknown/.code={% | |
\expandafter\pgfutil@in@\expandafter.\expandafter{\pgfkeyscurrentname}% | |
\ifpgfutil@in@ | |
\expandafter\forest@relatednode@option@setter\pgfkeyscurrentname=#1\forest@END | |
\else | |
\edef\forest@marshal{% | |
\noexpand\pgfkeysalso{node options={\pgfkeyscurrentname=\unexpanded{#1}}}% | |
}\forest@marshal | |
\fi | |
}, | |
get node boundary/.code={% | |
\forestoget{boundary}\forest@node@boundary | |
\def#1{}% | |
\forest@extendpath#1\forest@node@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}% | |
}, | |
% get min l tree boundary/.code={% | |
% \forest@get@tree@boundary{negative}{\the\numexpr\forestove{grow}-90\relax}#1}, | |
% get max l tree boundary/.code={% | |
% \forest@get@tree@boundary{positive}{\the\numexpr\forestove{grow}-90\relax}#1}, | |
get min s tree boundary/.code={% | |
\forest@get@tree@boundary{negative}{\forestove{grow}}#1}, | |
get max s tree boundary/.code={% | |
\forest@get@tree@boundary{positive}{\forestove{grow}}#1}, | |
fit to tree/.code={% | |
\pgfkeysalso{% | |
/forest/get min s tree boundary=\forest@temp@negative@boundary, | |
/forest/get max s tree boundary=\forest@temp@positive@boundary | |
}% | |
\edef\forest@temp@boundary{\expandonce{\forest@temp@negative@boundary}\expandonce{\forest@temp@positive@boundary}}% | |
\forest@path@getboundingrectangle@xy\forest@temp@boundary | |
\pgfkeysalso{inner sep=0,fit/.expanded={(\the\pgf@xa,\the\pgf@ya)(\the\pgf@xb,\the\pgf@yb)}}% | |
}, | |
use as bounding box/.style={% | |
before drawing tree={ | |
tikz+/.expanded={% | |
\noexpand\pgfresetboundingbox | |
\noexpand\useasboundingbox | |
($(.anchor)+(\forestoption{min x},\forestoption{min y})$) | |
rectangle | |
($(.anchor)+(\forestoption{max x},\forestoption{max y})$) | |
; | |
} | |
} | |
}, | |
use as bounding box'/.style={% | |
before drawing tree={ | |
tikz+/.expanded={% | |
\noexpand\pgfresetboundingbox | |
\noexpand\useasboundingbox | |
($(.anchor)+(\forestoption{min x}+\pgfkeysvalueof{/pgf/outer xsep}/2+\pgfkeysvalueof{/pgf/inner xsep},\forestoption{min y}+\pgfkeysvalueof{/pgf/outer ysep}/2+\pgfkeysvalueof{/pgf/inner ysep})$) | |
rectangle | |
($(.anchor)+(\forestoption{max x}-\pgfkeysvalueof{/pgf/outer xsep}/2-\pgfkeysvalueof{/pgf/inner xsep},\forestoption{max y}-\pgfkeysvalueof{/pgf/outer ysep}/2-\pgfkeysvalueof{/pgf/inner ysep})$) | |
; | |
} | |
} | |
}, | |
}% | |
\def\forest@get@tree@boundary#1#2#3{%#1=pos/neg,#2=grow,#3=receiving cs | |
\def#3{}% | |
\forest@node@getedge{#1}{#2}\forest@temp@boundary | |
\forest@extendpath#3\forest@temp@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}% | |
} | |
\def\forest@setter@node{\forest@cn}% | |
\def\forest@relatednode@option@setter#1.#2=#3\forest@END{% | |
\forest@forthis{% | |
\forest@nameandgo{#1}% | |
\let\forest@setter@node\forest@cn | |
}% | |
\pgfkeysalso{#2={#3}}% | |
\def\forest@setter@node{\forest@cn}% | |
}% | |
\forestset{ | |
for tree/.code={\forest@node@foreach{\pgfkeysalso{#1}}}, | |
if/.code n args={3}{% | |
\pgfmathparse{#1}% | |
\ifnum\pgfmathresult=0 \pgfkeysalso{#3}\else\pgfkeysalso{#2}\fi | |
}, | |
where/.style n args={3}{for tree={if={#1}{#2}{#3}}}, | |
for descendants/.code={\forest@node@foreachdescendant{\pgfkeysalso{#1}}}, | |
for all next/.style={for next={#1,for all next={#1}}}, | |
for all previous/.style={for previous={#1,for all previous={#1}}}, | |
for siblings/.style={for all previous={#1},for all next={#1}}, | |
for ancestors/.style={for parent={#1,for ancestors={#1}}}, | |
for ancestors'/.style={#1,for ancestors={#1}}, | |
for children/.code={\forest@node@foreachchild{\pgfkeysalso{#1}}}, | |
for c-commanded={for sibling={for tree={#1}}}, | |
for c-commanders={for sibling={#1},for parent={for c-commanders={#1}}} | |
} | |
\newcount\forest@repeat@key@depth | |
\forestset{% | |
repeat/.code 2 args={% | |
\advance\forest@repeat@key@depth1 | |
\pgfmathparse{int(#1)}% | |
\csedef{forest@repeat@key@\the\forest@repeat@key@depth}{\pgfmathresult}% | |
\expandafter\newloop\csname forest@repeat@key@loop@\the\forest@repeat@key@depth\endcsname | |
\def\forest@marshal{% | |
\csname forest@repeat@key@loop@\the\forest@repeat@key@depth\endcsname | |
\forest@temp@count=\csname forest@repeat@key@\the\forest@repeat@key@depth\endcsname\relax | |
\ifnum\forest@temp@count>0 | |
\advance\forest@temp@count-1 | |
\csedef{forest@repeat@key@\the\forest@repeat@key@depth}{\the\forest@temp@count}% | |
\pgfkeysalso{#2}% | |
}% | |
\expandafter\forest@marshal\csname forest@repeat@key@repeat@\the\forest@repeat@key@depth\endcsname | |
\advance\forest@repeat@key@depth-1 | |
}, | |
} | |
\pgfkeysgetvalue{/forest/repeat/.@cmd}\forest@temp | |
\pgfkeyslet{/forest/node walk/repeat/.@cmd}\forest@temp | |
\pgfmathdeclarefunction{strequal}{2}{% | |
\ifstrequal{#1}{#2}{\def\pgfmathresult{1}}{\def\pgfmathresult{0}}% | |
} | |
\pgfmathdeclarefunction{instr}{2}{% | |
\pgfutil@in@{#1}{#2}% | |
\ifpgfutil@in@\def\pgfmathresult{1}\else\def\pgfmathresult{0}\fi | |
} | |
\pgfmathdeclarefunction{strcat}{...}{% | |
\edef\pgfmathresult{\forest@strip@braces{#1}}% | |
} | |
\def\forest@pgfmathhelper@attribute@toks#1#2{% | |
\forest@forthis{% | |
\forest@nameandgo{#1}% | |
\forestoget{#2}\pgfmathresult | |
}% | |
} | |
\def\forest@pgfmathhelper@attribute@dimen#1#2{% | |
\forest@forthis{% | |
\forest@nameandgo{#1}% | |
\forestoget{#2}\forest@temp | |
\pgfmathparse{+\forest@temp}% | |
}% | |
} | |
\def\forest@pgfmathhelper@attribute@count#1#2{% | |
\forest@forthis{% | |
\forest@nameandgo{#1}% | |
\forestoget{#2}\forest@temp | |
\pgfmathtruncatemacro\pgfmathresult{\forest@temp}% | |
}% | |
} | |
\pgfmathdeclarefunction{id}{1}{% | |
\forest@forthis{% | |
\forest@nameandgo{#1}% | |
\let\pgfmathresult\forest@cn | |
}% | |
} | |
\forestset{% | |
if id/.code n args={3}{% | |
\ifnum#1=\forest@cn\relax | |
\pgfkeysalso{#2}% | |
\else | |
\pgfkeysalso{#3}% | |
\fi | |
}, | |
where id/.style n args={3}{for tree={if id={#1}{#2}{#3}}} | |
} | |
\def\forest@last@node{0} | |
\def\forest@nodehandleby@name@nodewalk@or@bracket#1{% | |
\ifx\pgfkeysnovalue#1% | |
\edef\forest@last@node{\forest@node@Nametoid{forest@last@node}}% | |
\else | |
\forest@nodehandleby@nnb@checkfirst#1\forest@END | |
\fi | |
} | |
\def\forest@nodehandleby@nnb@checkfirst#1#2\forest@END{% | |
\ifx[#1%] | |
\forest@create@node{#1#2}% | |
\else | |
\forest@forthis{% | |
\forest@nameandgo{#1#2}% | |
\let\forest@last@node\forest@cn | |
}% | |
\fi | |
} | |
\def\forest@create@node#1{% #1=bracket representation | |
\bracketParse{\forest@create@collectafterthought}% | |
\forest@last@node=#1\forest@end@create@node | |
} | |
\def\forest@create@collectafterthought#1\forest@end@create@node{% | |
\forestOletO{\forest@last@node}{delay}{\forest@last@node}{given options}% | |
\forestOset{\forest@last@node}{given options}{}% | |
\forestOeappto{\forest@last@node}{delay}{,\unexpanded{#1}}% | |
} | |
\def\forest@create@collectafterthought#1\forest@end@create@node{% | |
\forest@node@Foreach{\forest@last@node}{% | |
\forestoleto{delay}{given options}% | |
\forestoset{given options}{}% | |
}% | |
\forestOeappto{\forest@last@node}{delay}{,\unexpanded{#1}}% | |
} | |
\def\forest@remove@node#1{% | |
\forest@node@Remove{#1}% | |
} | |
\def\forest@append@node#1#2{% | |
\forest@node@Remove{#2}% | |
\forest@node@Append{#1}{#2}% | |
} | |
\def\forest@prepend@node#1#2{% | |
\forest@node@Remove{#2}% | |
\forest@node@Prepend{#1}{#2}% | |
} | |
\def\forest@insertafter@node#1#2{% | |
\forest@node@Remove{#2}% | |
\forest@node@Insertafter{\forestOve{#1}{@parent}}{#2}{#1}% | |
} | |
\def\forest@insertbefore@node#1#2{% | |
\forest@node@Remove{#2}% | |
\forest@node@Insertbefore{\forestOve{#1}{@parent}}{#2}{#1}% | |
} | |
\def\forest@appto@do@dynamics#1#2{% | |
\forest@nodehandleby@name@nodewalk@or@bracket{#2}% | |
\ifcase\forest@dynamics@copyhow\relax\or | |
\forest@tree@copy{\forest@last@node}\forest@last@node | |
\or | |
\forest@node@copy{\forest@last@node}\forest@last@node | |
\fi | |
\forest@node@Ifnamedefined{forest@last@node}{% | |
\forestOepreto{\forest@last@node}{delay} | |
{for id={\forest@node@Nametoid{forest@last@node}}{alias=forest@last@node},}% | |
}{}% | |
\forest@havedelayedoptionstrue | |
\edef\forest@marshal{% | |
\noexpand\apptotoks\noexpand\forest@do@dynamics{% | |
\noexpand#1{\forest@cn}{\forest@last@node}}% | |
}\forest@marshal | |
} | |
\forestset{% | |
create/.code={\forest@create@node{#1}}, | |
append/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@append@node{#1}}, | |
prepend/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@prepend@node{#1}}, | |
insert after/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, | |
insert before/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, | |
append'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@append@node{#1}}, | |
prepend'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@prepend@node{#1}}, | |
insert after'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, | |
insert before'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, | |
append''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@append@node{#1}}, | |
prepend''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@prepend@node{#1}}, | |
insert after''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, | |
insert before''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, | |
remove/.code={% | |
\pgfkeysalso{alias=forest@last@node}% | |
\expandafter\apptotoks\expandafter\forest@do@dynamics\expandafter{% | |
\expandafter\forest@remove@node\expandafter{\forest@cn}}% | |
}, | |
set root/.code={% | |
\forest@nodehandleby@name@nodewalk@or@bracket{#1}% | |
\edef\forest@marshal{% | |
\noexpand\apptotoks\noexpand\forest@do@dynamics{% | |
\def\noexpand\forest@root{\forest@last@node}% | |
}% | |
}\forest@marshal | |
}, | |
replace by/.code={\forest@replaceby@code{#1}{insert after}}, | |
replace by'/.code={\forest@replaceby@code{#1}{insert after'}}, | |
replace by''/.code={\forest@replaceby@code{#1}{insert after''}}, | |
} | |
\def\forest@replaceby@code#1#2{%#1=node spec,#2=insert after[']['] | |
\ifnum\forestove{@parent}=0 | |
\pgfkeysalso{set root={#1}}% | |
\else | |
\pgfkeysalso{alias=forest@last@node,#2={#1}}% | |
\eapptotoks\forest@do@dynamics{% | |
\noexpand\ifnum\noexpand\forestOve{\forest@cn}{@parent}=\forestove{@parent} | |
\noexpand\forest@remove@node{\forest@cn}% | |
\noexpand\fi | |
}% | |
\fi | |
} | |
\forestset{ | |
stages/.style={ | |
process keylist=before typesetting nodes, | |
typeset nodes stage, | |
process keylist=before packing, | |
pack stage, | |
process keylist=before computing xy, | |
compute xy stage, | |
process keylist=before drawing tree, | |
draw tree stage, | |
}, | |
typeset nodes stage/.style={for root'=typeset nodes}, | |
pack stage/.style={for root'=pack}, | |
compute xy stage/.style={for root'=compute xy}, | |
draw tree stage/.style={for root'=draw tree}, | |
process keylist/.code={\forest@process@hook@keylist{#1}}, | |
declare keylist={given options}{}, | |
declare keylist={before typesetting nodes}{}, | |
declare keylist={before packing}{}, | |
declare keylist={before computing xy}{}, | |
declare keylist={before drawing tree}{}, | |
declare keylist={delay}{}, | |
delay/.append code={\forest@havedelayedoptionstrue}, | |
delay n/.style 2 args={if={#1==0}{#2}{delay@n={#1}{#2}}}, | |
delay@n/.style 2 args={ | |
if={#1==1}{delay={#2}}{delay={delay@n/.wrap pgfmath arg={{##1}{#2}}{#1-1}}} | |
}, | |
if have delayed/.code 2 args={% | |
\ifforest@havedelayedoptions\pgfkeysalso{#1}\else\pgfkeysalso{#2}\fi | |
}, | |
typeset nodes/.code={% | |
\forest@drawtree@preservenodeboxes@false | |
\forest@node@foreach{\forest@node@typeset}}, | |
typeset nodes'/.code={% | |
\forest@drawtree@preservenodeboxes@true | |
\forest@node@foreach{\forest@node@typeset}}, | |
typeset node/.code={% | |
\forest@drawtree@preservenodeboxes@false | |
\forest@node@typeset | |
}, | |
pack/.code={\forest@pack}, | |
pack'/.code={\forest@pack@onlythisnode}, | |
compute xy/.code={\forest@node@computeabsolutepositions}, | |
draw tree box/.store in=\forest@drawtreebox, | |
draw tree box, | |
draw tree/.code={% | |
\forest@drawtree@preservenodeboxes@false | |
\forest@node@drawtree | |
}, | |
draw tree'/.code={% | |
\forest@drawtree@preservenodeboxes@true | |
\forest@node@drawtree | |
}, | |
} | |
\newtoks\forest@do@dynamics | |
\newif\ifforest@havedelayedoptions | |
\def\forest@process@hook@keylist#1{% | |
\forest@loopa | |
\forest@havedelayedoptionsfalse | |
\forest@do@dynamics={}% | |
\forest@fornode{\forest@root}{\forest@process@hook@keylist@{#1}}% | |
\expandafter\ifstrempty\expandafter{\the\forest@do@dynamics}{}{% | |
\the\forest@do@dynamics | |
\forest@node@Compute@numeric@ts@info{\forest@root}% | |
\forest@havedelayedoptionstrue | |
}% | |
\ifforest@havedelayedoptions | |
\forest@node@Foreach{\forest@root}{% | |
\forestoget{delay}\forest@temp@delayed | |
\forestolet{#1}\forest@temp@delayed | |
\forestoset{delay}{}% | |
}% | |
\forest@repeata | |
} | |
\def\forest@process@hook@keylist@#1{% | |
\forest@node@foreach{% | |
\forestoget{#1}\forest@temp@keys | |
\ifdefvoid\forest@temp@keys{}{% | |
\forestoset{#1}{}% | |
\expandafter\forestset\expandafter{\forest@temp@keys}% | |
}% | |
}% | |
} | |
\def\forest@node@typeset{% | |
\let\forest@next\forest@node@typeset@ | |
\forestoifdefined{box}{% | |
\ifforest@drawtree@preservenodeboxes@ | |
\let\forest@next\relax | |
\fi | |
}{% | |
\locbox\forest@temp@box | |
\forestolet{box}\forest@temp@box | |
}% | |
\def\forest@node@typeset@restore{}% | |
\ifdefined\ifsa@tikz\forest@standalone@hack\fi | |
\forest@next | |
\forest@node@typeset@restore | |
} | |
\def\forest@standalone@hack{% | |
\ifsa@tikz | |
\let\forest@standalone@tikzpicture\tikzpicture | |
\let\forest@standalone@endtikzpicture\endtikzpicture | |
\let\tikzpicture\sa@orig@tikzpicture | |
\let\endtikzpicture\sa@orig@endtikzpicture | |
\def\forest@node@typeset@restore{% | |
\let\tikzpicture\forest@standalone@tikzpicture | |
\let\endtikzpicture\forest@standalone@endtikzpicture | |
}% | |
\fi | |
} | |
\newbox\forest@box | |
\def\forest@node@typeset@{% | |
\forestoget{name}\forest@nodename | |
\edef\forest@temp@nodeformat{\forestove{node format}}% | |
\gdef\forest@smuggle{}% | |
\setbox0=\hbox{% | |
\begin{tikzpicture}% | |
\pgfpositionnodelater{\forest@positionnodelater@save}% | |
\forest@temp@nodeformat | |
\pgfinterruptpath | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{forestcomputenodeboundary}% | |
\endpgfinterruptpath | |
%\forest@compute@node@boundary\forest@temp | |
%\xappto\forest@smuggle{\noexpand\forestoset{boundary}{\expandonce\forest@temp}}% | |
\if\relax\forestove{parent anchor}\relax | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{center}% | |
\else | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{\forestove{parent anchor}}% | |
\fi | |
\xappto\forest@smuggle{% | |
\noexpand\forestoset{parent@anchor}{% | |
\noexpand\noexpand\noexpand\pgf@x=\the\pgf@x\relax | |
\noexpand\noexpand\noexpand\pgf@y=\the\pgf@y\relax}}% | |
\if\relax\forestove{child anchor}\relax | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{center}% | |
\else | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{\forestove{child anchor}}% | |
\fi | |
\xappto\forest@smuggle{% | |
\noexpand\forestoeset{child@anchor}{% | |
\noexpand\noexpand\noexpand\pgf@x=\the\pgf@x\relax | |
\noexpand\noexpand\noexpand\pgf@y=\the\pgf@y\relax}}% | |
\if\relax\forestove{anchor}\relax | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{center}% | |
\else | |
\pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{\forestove{anchor}}% | |
\fi | |
\xappto\forest@smuggle{% | |
\noexpand\forestoeset{@anchor}{% | |
\noexpand\noexpand\noexpand\pgf@x=\the\pgf@x\relax | |
\noexpand\noexpand\noexpand\pgf@y=\the\pgf@y\relax}}% | |
\end{tikzpicture}% | |
}% | |
\setbox\forestove{box}=\box\forest@box % smuggle the box | |
\forestolet{boundary}\forest@global@boundary | |
\forest@smuggle % ... and the rest | |
} | |
\forestset{ | |
declare readonly dimen={min x}, | |
declare readonly dimen={min y}, | |
declare readonly dimen={max x}, | |
declare readonly dimen={max y}, | |
} | |
\def\forest@patch@enormouscoordinateboxbounds@plus#1{% | |
\expandafter\ifstrequal\expandafter{#1}{16000.0pt}{\def#1{0.0pt}}{}% | |
} | |
\def\forest@patch@enormouscoordinateboxbounds@minus#1{% | |
\expandafter\ifstrequal\expandafter{#1}{-16000.0pt}{\def#1{0.0pt}}{}% | |
} | |
\def\forest@positionnodelater@save{% | |
\global\setbox\forest@box=\box\pgfpositionnodelaterbox | |
\xappto\forest@smuggle{\noexpand\forestoset{later@name}{\pgfpositionnodelatername}}% | |
% a bug in pgf? ---well, here's a patch | |
\forest@patch@enormouscoordinateboxbounds@plus\pgfpositionnodelaterminx | |
\forest@patch@enormouscoordinateboxbounds@plus\pgfpositionnodelaterminy | |
\forest@patch@enormouscoordinateboxbounds@minus\pgfpositionnodelatermaxx | |
\forest@patch@enormouscoordinateboxbounds@minus\pgfpositionnodelatermaxy | |
% end of patch | |
\xappto\forest@smuggle{\noexpand\forestoset{min x}{\pgfpositionnodelaterminx}}% | |
\xappto\forest@smuggle{\noexpand\forestoset{min y}{\pgfpositionnodelaterminy}}% | |
\xappto\forest@smuggle{\noexpand\forestoset{max x}{\pgfpositionnodelatermaxx}}% | |
\xappto\forest@smuggle{\noexpand\forestoset{max y}{\pgfpositionnodelatermaxy}}% | |
} | |
\def\forest@node@forest@positionnodelater@restore{% | |
\ifforest@drawtree@preservenodeboxes@ | |
\let\forest@boxorcopy\copy | |
\else | |
\let\forest@boxorcopy\box | |
\fi | |
\forestoget{box}\forest@temp | |
\setbox\pgfpositionnodelaterbox=\forest@boxorcopy\forest@temp | |
\edef\pgfpositionnodelatername{\forestove{later@name}}% | |
\edef\pgfpositionnodelaterminx{\forestove{min x}}% | |
\edef\pgfpositionnodelaterminy{\forestove{min y}}% | |
\edef\pgfpositionnodelatermaxx{\forestove{max x}}% | |
\edef\pgfpositionnodelatermaxy{\forestove{max y}}% | |
} | |
\def\forest@pack{% | |
\forest@pack@computetiers | |
\forest@pack@computegrowthuniformity | |
\forest@@pack | |
} | |
\def\forest@@pack{% | |
\ifnum\forestove{n children}>0 | |
\ifnum\forestove{uniform growth}>0 | |
\forest@pack@level@uniform | |
\forest@pack@aligntiers@ofsubtree | |
\forest@pack@sibling@uniform@recursive | |
\else | |
\forest@node@foreachchild{\forest@@pack}% | |
\forest@pack@level@nonuniform | |
\forest@pack@aligntiers | |
\forest@pack@sibling@uniform@applyreversed | |
\fi | |
\fi | |
} | |
\def\forest@pack@onlythisnode{% | |
\ifnum\forestove{n children}>0 | |
\forest@pack@computetiers | |
\forest@pack@level@nonuniform | |
\forest@pack@aligntiers | |
\forest@pack@sibling@uniform@applyreversed | |
\fi | |
} | |
\def\forest@pack@computegrowthuniformity{% | |
\forest@node@foreachchild{\forest@pack@computegrowthuniformity}% | |
\edef\forest@pack@cgu@uniformity{% | |
\ifnum\forestove{n children}=0 | |
2\else 1\fi | |
}% | |
\forestoget{grow}\forest@pack@cgu@parentgrow | |
\forest@node@foreachchild{% | |
\ifnum\forestove{uniform growth}=0 | |
\def\forest@pack@cgu@uniformity{0}% | |
\else | |
\ifnum\forestove{uniform growth}=1 | |
\ifnum\forestove{grow}=\forest@pack@cgu@parentgrow\relax\else | |
\def\forest@pack@cgu@uniformity{0}% | |
\fi | |
\fi | |
\fi | |
}% | |
\forestolet{uniform growth}\forest@pack@cgu@uniformity | |
} | |
\def\forest@pack@level@uniform{% | |
\let\forest@plu@minchildl\relax | |
\forestoget{grow}\forest@plu@grow | |
\forest@node@foreachchild{% | |
\forest@node@getboundingrectangle@ls{\forest@plu@grow}% | |
\advance\pgf@xa\forestove{l}\relax | |
\ifx\forest@plu@minchildl\relax | |
\edef\forest@plu@minchildl{\the\pgf@xa}% | |
\else | |
\ifdim\pgf@xa<\forest@plu@minchildl\relax | |
\edef\forest@plu@minchildl{\the\pgf@xa}% | |
\fi | |
\fi | |
}% | |
\forest@node@getboundingrectangle@ls{\forest@plu@grow}% | |
\pgfutil@tempdima=\pgf@xb\relax | |
\advance\pgfutil@tempdima -\forest@plu@minchildl\relax | |
\advance\pgfutil@tempdima \forestove{l sep}\relax | |
\ifdim\pgfutil@tempdima>0pt | |
\forest@node@foreachchild{% | |
\forestoeset{l}{\the\dimexpr\forestove{l}+\the\pgfutil@tempdima}% | |
}% | |
\fi | |
\forest@node@foreachchild{% | |
\ifnum\forestove{n children}>0 | |
\forest@pack@level@uniform | |
\fi | |
}% | |
} | |
\def\forest@pack@level@nonuniform{% | |
\let\forest@plu@minchildl\relax | |
\forestoget{grow}\forest@plu@grow | |
\forest@node@foreachchild{% | |
\forest@node@getedge{negative}{\forest@plu@grow}{\forest@plnu@negativechildedge}% | |
\forest@node@getedge{positive}{\forest@plu@grow}{\forest@plnu@positivechildedge}% | |
\def\forest@plnu@childedge{\forest@plnu@negativechildedge\forest@plnu@positivechildedge}% | |
\forest@path@getboundingrectangle@ls\forest@plnu@childedge{\forest@plu@grow}% | |
\advance\pgf@xa\forestove{l}\relax | |
\ifx\forest@plu@minchildl\relax | |
\edef\forest@plu@minchildl{\the\pgf@xa}% | |
\else | |
\ifdim\pgf@xa<\forest@plu@minchildl\relax | |
\edef\forest@plu@minchildl{\the\pgf@xa}% | |
\fi | |
\fi | |
}% | |
\forest@node@getboundingrectangle@ls{\forest@plu@grow}% | |
\pgfutil@tempdima=\pgf@xb\relax | |
\advance\pgfutil@tempdima -\forest@plu@minchildl\relax | |
\advance\pgfutil@tempdima \forestove{l sep}\relax | |
\ifdim\pgfutil@tempdima>0pt | |
\forest@node@foreachchild{% | |
\forestoeset{l}{\the\dimexpr\the\pgfutil@tempdima+\forestove{l}}% | |
}% | |
\fi | |
} | |
\def\forest@pack@aligntiers{% | |
\forestoget{grow}\forest@temp@parentgrow | |
\forestoget{@tiers}\forest@temp@tiers | |
\forlistloop\forest@pack@aligntier@\forest@temp@tiers | |
} | |
\def\forest@pack@aligntiers@ofsubtree{% | |
\forest@node@foreach{\forest@pack@aligntiers}% | |
} | |
\def\forest@pack@aligntiers@computeabsl{% | |
\forestoleto{abs@l}{l}% | |
\forest@node@foreachdescendant{\forest@pack@aligntiers@computeabsl@}% | |
} | |
\def\forest@pack@aligntiers@computeabsl@{% | |
\forestoeset{abs@l}{\the\dimexpr\forestove{l}+\forestOve{\forestove{@parent}}{abs@l}}% | |
} | |
\def\forest@pack@aligntier@#1{% | |
\forest@pack@aligntiers@computeabsl | |
\pgfutil@tempdima=-\maxdimen\relax | |
\def\forest@temp@currenttier{#1}% | |
\forest@node@foreach{% | |
\forestoget{tier}\forest@temp@tier | |
\ifx\forest@temp@currenttier\forest@temp@tier | |
\ifdim\pgfutil@tempdima<\forestove{abs@l}\relax | |
\pgfutil@tempdima=\forestove{abs@l}\relax | |
\fi | |
\fi | |
}% | |
\ifdim\pgfutil@tempdima=-\maxdimen\relax\else | |
\forest@node@foreach{% | |
\forestoget{tier}\forest@temp@tier | |
\ifx\forest@temp@currenttier\forest@temp@tier | |
\forestoeset{l}{\the\dimexpr\pgfutil@tempdima-\forestove{abs@l}+\forestove{l}}% | |
\fi | |
}% | |
\fi | |
} | |
\def\forest@pack@sibling@uniform@recursive{% | |
\forest@node@foreachchild{\forest@pack@sibling@uniform@recursive}% | |
\forest@pack@sibling@uniform@applyreversed | |
} | |
\def\forest@pack@sibling@uniform@applyreversed{% | |
\ifnum\forestove{n children}>1 | |
\ifnum\forestove{reversed}=0 | |
\pack@sibling@uniform@main{first}{last}{next}{previous}% | |
\else | |
\pack@sibling@uniform@main{last}{first}{previous}{next}% | |
\fi | |
\fi | |
} | |
\def\pack@sibling@uniform@main#1#2#3#4{% | |
\forestoget{@#1}\forest@child | |
\edef\forest@temp{% | |
\noexpand\forest@fornode{\forestove{@#1}}{% | |
\noexpand\forest@node@getedge | |
{positive} | |
{\forestove{grow}} | |
\noexpand\forest@temp@edge | |
}% | |
}\forest@temp | |
\forest@pack@pgfpoint@childsposition\forest@child | |
\let\forest@previous@positive@edge\pgfutil@empty | |
\forest@extendpath\forest@previous@positive@edge\forest@temp@edge{}% | |
\forestOget{\forest@child}{@#3}\forest@child | |
\edef\forest@previous@child@s{0pt}% | |
\forest@loopb | |
\unless\ifnum\forest@child=0 | |
\edef\forest@temp{% | |
\noexpand\forest@fornode{\forest@child}{% | |
\noexpand\forest@node@getedge | |
{negative} | |
{\forestove{grow}} | |
\noexpand\forest@temp@edge | |
}% | |
}\forest@temp | |
\forest@pack@pgfpoint@childsposition\forest@child | |
\let\forest@child@negative@edge\pgfutil@empty | |
\forest@extendpath\forest@child@negative@edge\forest@temp@edge{}% | |
\forest@setupgrowline{\forestove{grow}}% | |
\forest@distance@between@edge@paths\forest@previous@positive@edge\forest@child@negative@edge\forest@csdistance | |
\ifx\forest@csdistance\relax | |
%\forestOeset{\forest@child}{s}{\forest@previous@child@s}% | |
\else | |
\advance\pgfutil@tempdimb-\forest@csdistance\relax | |
\advance\pgfutil@tempdimb\forestove{s sep}\relax | |
\forestOeset{\forest@child}{s}{\the\dimexpr\forestove{s}-\forest@csdistance+\forestove{s sep}}% | |
\fi | |
\ifdim\forestOve{\forest@child}{s}<\forest@previous@child@s\relax | |
\forestOeset{\forest@child}{s}{\forest@previous@child@s}% | |
\fi | |
\forestOget{\forest@child}{s}\forest@child@s | |
\edef\forest@previous@child@s{\forest@child@s}% | |
\edef\forest@temp{% | |
\noexpand\forest@fornode{\forest@child}{% | |
\noexpand\forest@node@getedge | |
{positive} | |
{\forestove{grow}} | |
\noexpand\forest@temp@edge | |
}% | |
}\forest@temp | |
\forest@pack@pgfpoint@childsposition\forest@child | |
\forest@extendpath\forest@previous@positive@edge\forest@temp@edge{}% | |
\forest@getpositivetightedgeofpath\forest@previous@positive@edge\forest@previous@positive@edge | |
\forestOget{\forest@child}{@#3}\forest@child | |
\forest@repeatb | |
\csname forest@calign@\forestove{calign}\endcsname | |
} | |
\def\forest@pack@pgfpoint@childsposition#1{% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forestove{grow}}% | |
\forest@fornode{#1}{% | |
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% | |
}% | |
}% | |
} | |
\def\forest@pack@pgfpoint@positioningrow#1{% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{#1}% | |
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% | |
}% | |
} | |
\def\forest@calign@s@shift#1{% | |
\pgfutil@tempdima=#1\relax | |
\forest@node@foreachchild{% | |
\forestoeset{s}{\the\dimexpr\forestove{s}+\pgfutil@tempdima}% | |
}% | |
} | |
\def\forest@calign@child{% | |
\forest@calign@s@shift{-\forestOve{\forest@node@nornbarthchildid{\forestove{calign primary child}}}{s}}% | |
} | |
\csdef{forest@calign@child edge}{% | |
{% | |
\edef\forest@temp@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% | |
\pgftransformreset | |
\pgftransformrotate{\forestove{grow}}% | |
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest@temp@child}{l}}{\forestOve{\forest@temp@child}{s}}}% | |
\pgf@xa=\pgf@x\relax\pgf@ya=\pgf@y\relax | |
\forestOve{\forest@temp@child}{child@anchor}% | |
\advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax | |
\forestove{parent@anchor}% | |
\advance\pgf@xa-\pgf@x\relax\advance\pgf@ya-\pgf@y\relax | |
\edef\forest@marshal{% | |
\noexpand\pgftransformreset | |
\noexpand\pgftransformrotate{-\forestove{grow}}% | |
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% | |
}\forest@marshal | |
}% | |
\forest@calign@s@shift{\the\dimexpr-\the\pgf@y}% | |
} | |
\csdef{forest@calign@midpoint}{% | |
\forest@calign@s@shift{\the\dimexpr 0pt -% | |
(\forestOve{\forest@node@nornbarthchildid{\forestove{calign primary child}}}{s}% | |
+\forestOve{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}{s}% | |
)/2\relax | |
}% | |
} | |
\csdef{forest@calign@edge midpoint}{% | |
{% | |
\edef\forest@temp@firstchild{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% | |
\edef\forest@temp@secondchild{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% | |
\pgftransformreset | |
\pgftransformrotate{\forestove{grow}}% | |
\pgfpointtransformed{\pgfqpoint{\forestOve{\forest@temp@firstchild}{l}}{\forestOve{\forest@temp@firstchild}{s}}}% | |
\pgf@xa=\pgf@x\relax\pgf@ya=\pgf@y\relax | |
\forestOve{\forest@temp@firstchild}{child@anchor}% | |
\advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax | |
\edef\forest@marshal{% | |
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\forestOve{\forest@temp@secondchild}{l}}{\forestOve{\forest@temp@secondchild}{s}}}% | |
}\forest@marshal | |
\advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax | |
\forestOve{\forest@temp@secondchild}{child@anchor}% | |
\advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax | |
\divide\pgf@xa2 \divide\pgf@ya2 | |
\edef\forest@marshal{% | |
\noexpand\pgftransformreset | |
\noexpand\pgftransformrotate{-\forestove{grow}}% | |
\noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% | |
}\forest@marshal | |
}% | |
\forest@calign@s@shift{\the\dimexpr-\the\pgf@y}% | |
} | |
\csdef{forest@calign@fixed angles}{% | |
\edef\forest@ca@first@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% | |
\edef\forest@ca@second@child{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% | |
\ifnum\forestove{reversed}=1 | |
\let\forest@temp\forest@ca@first@child | |
\let\forest@ca@first@child\forest@ca@second@child | |
\let\forest@ca@second@child\forest@temp | |
\fi | |
\forestOget{\forest@ca@first@child}{l}\forest@ca@first@l | |
\forestOget{\forest@ca@second@child}{l}\forest@ca@second@l | |
\pgfmathsetlengthmacro\forest@ca@desired@s@distance{% | |
tan(\forestove{calign secondary angle})*\forest@ca@second@l | |
-tan(\forestove{calign primary angle})*\forest@ca@first@l | |
}% | |
\forestOget{\forest@ca@first@child}{s}\forest@ca@first@s | |
\forestOget{\forest@ca@second@child}{s}\forest@ca@second@s | |
\pgfmathsetlengthmacro\forest@ca@actual@s@distance{% | |
\forest@ca@second@s-\forest@ca@first@s}% | |
\ifdim\forest@ca@desired@s@distance>\forest@ca@actual@s@distance\relax | |
\ifdim\forest@ca@actual@s@distance=0pt | |
\pgfmathsetlength\pgfutil@tempdima{tan(\forestove{calign primary angle})*\forest@ca@second@l}% | |
\pgfmathsetlength\pgfutil@tempdimb{\forest@ca@desired@s@distance/(\forestove{n children}-1)}% | |
\forest@node@foreachchild{% | |
\forestoeset{s}{\the\pgfutil@tempdima}% | |
\advance\pgfutil@tempdima\pgfutil@tempdimb | |
}% | |
\def\forest@calign@anchor{0pt}% | |
\else | |
\pgfmathsetmacro\forest@ca@ratio{% | |
\forest@ca@desired@s@distance/\forest@ca@actual@s@distance}% | |
\forest@node@foreachchild{% | |
\pgfmathsetlengthmacro\forest@temp{\forest@ca@ratio*\forestove{s}}% | |
\forestolet{s}\forest@temp | |
}% | |
\pgfmathsetlengthmacro\forest@calign@anchor{% | |
-tan(\forestove{calign primary angle})*\forest@ca@first@l}% | |
\fi | |
\else | |
\ifdim\forest@ca@desired@s@distance<\forest@ca@actual@s@distance\relax | |
\pgfmathsetlengthmacro\forest@ca@ratio{% | |
\forest@ca@actual@s@distance/\forest@ca@desired@s@distance}% | |
\forest@node@foreachchild{% | |
\pgfmathsetlengthmacro\forest@temp{\forest@ca@ratio*\forestove{l}}% | |
\forestolet{l}\forest@temp | |
}% | |
\forestOget{\forest@ca@first@child}{l}\forest@ca@first@l | |
\pgfmathsetlengthmacro\forest@calign@anchor{% | |
-tan(\forestove{calign primary angle})*\forest@ca@first@l}% | |
\fi | |
\fi | |
\forest@calign@s@shift{-\forest@calign@anchor}% | |
} | |
\csdef{forest@calign@fixed edge angles}{% | |
\edef\forest@ca@first@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% | |
\edef\forest@ca@second@child{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% | |
\ifnum\forestove{reversed}=1 | |
\let\forest@temp\forest@ca@first@child | |
\let\forest@ca@first@child\forest@ca@second@child | |
\let\forest@ca@second@child\forest@temp | |
\fi | |
\forestOget{\forest@ca@first@child}{l}\forest@ca@first@l | |
\forestOget{\forest@ca@second@child}{l}\forest@ca@second@l | |
\forestoget{parent@anchor}\forest@ca@parent@anchor | |
\forest@ca@parent@anchor | |
\edef\forest@ca@parent@anchor@s{\the\pgf@x}% | |
\edef\forest@ca@parent@anchor@l{\the\pgf@y}% | |
\forestOget{\forest@ca@first@child}{child@anchor}\forest@ca@first@child@anchor | |
\forest@ca@first@child@anchor | |
\edef\forest@ca@first@child@anchor@s{\the\pgf@x}% | |
\edef\forest@ca@first@child@anchor@l{\the\pgf@y}% | |
\forestOget{\forest@ca@second@child}{child@anchor}\forest@ca@second@child@anchor | |
\forest@ca@second@child@anchor | |
\edef\forest@ca@second@child@anchor@s{\the\pgf@x}% | |
\edef\forest@ca@second@child@anchor@l{\the\pgf@y}% | |
\pgfmathsetlengthmacro\forest@ca@desired@second@edge@s{tan(\forestove{calign secondary angle})*% | |
(\forest@ca@second@l-\forest@ca@second@child@anchor@l+\forest@ca@parent@anchor@l)}% | |
\pgfmathsetlengthmacro\forest@ca@desired@first@edge@s{tan(\forestove{calign primary angle})*% | |
(\forest@ca@first@l-\forest@ca@first@child@anchor@l+\forest@ca@parent@anchor@l)} | |
\pgfmathsetlengthmacro\forest@ca@desired@s@distance{\forest@ca@desired@second@edge@s-\forest@ca@desired@first@edge@s}% | |
\forestOget{\forest@ca@first@child}{s}\forest@ca@first@s | |
\forestOget{\forest@ca@second@child}{s}\forest@ca@second@s | |
\pgfmathsetlengthmacro\forest@ca@actual@s@distance{% | |
\forest@ca@second@s+\forest@ca@second@child@anchor@s | |
-\forest@ca@first@s-\forest@ca@first@child@anchor@s}% | |
\ifdim\forest@ca@desired@s@distance>\forest@ca@actual@s@distance\relax | |
\ifdim\forest@ca@actual@s@distance=0pt | |
\forestoget{n children}\forest@temp@n@children | |
\forest@node@foreachchild{% | |
\forestoget{child@anchor}\forest@temp@child@anchor | |
\forest@temp@child@anchor | |
\edef\forest@temp@child@anchor@s{\the\pgf@x}% | |
\pgfmathsetlengthmacro\forest@temp{% | |
\forest@ca@desired@first@edge@s+(\forestove{n}-1)*\forest@ca@desired@s@distance/(\forest@temp@n@children-1)+\forest@ca@first@child@anchor@s-\forest@temp@child@anchor@s}% | |
\forestolet{s}\forest@temp | |
}% | |
\def\forest@calign@anchor{0pt}% | |
\else | |
\pgfmathsetmacro\forest@ca@ratio{% | |
\forest@ca@desired@s@distance/\forest@ca@actual@s@distance}% | |
\forest@node@foreachchild{% | |
\forestoget{child@anchor}\forest@temp@child@anchor | |
\forest@temp@child@anchor | |
\edef\forest@temp@child@anchor@s{\the\pgf@x}% | |
\pgfmathsetlengthmacro\forest@temp{% | |
\forest@ca@ratio*(% | |
\forestove{s}-\forest@ca@first@s | |
+\forest@temp@child@anchor@s-\forest@ca@first@child@anchor@s)% | |
+\forest@ca@first@s | |
+\forest@ca@first@child@anchor@s-\forest@temp@child@anchor@s}% | |
\forestolet{s}\forest@temp | |
}% | |
\pgfmathsetlengthmacro\forest@calign@anchor{% | |
-tan(\forestove{calign primary angle})*(\forest@ca@first@l-\forest@ca@first@child@anchor@l+\forest@ca@parent@anchor@l)% | |
+\forest@ca@first@child@anchor@s-\forest@ca@parent@anchor@s | |
}% | |
\fi | |
\else | |
\ifdim\forest@ca@desired@s@distance<\forest@ca@actual@s@distance\relax | |
\pgfmathsetlengthmacro\forest@ca@ratio{% | |
\forest@ca@actual@s@distance/\forest@ca@desired@s@distance}% | |
\forest@node@foreachchild{% | |
\forestoget{child@anchor}\forest@temp@child@anchor | |
\forest@temp@child@anchor | |
\edef\forest@temp@child@anchor@l{\the\pgf@y}% | |
\pgfmathsetlengthmacro\forest@temp{% | |
\forest@ca@ratio*(% | |
\forestove{l}+\forest@ca@parent@anchor@l-\forest@temp@child@anchor@l) | |
-\forest@ca@parent@anchor@l+\forest@temp@child@anchor@l}% | |
\forestolet{l}\forest@temp | |
}% | |
\forestOget{\forest@ca@first@child}{l}\forest@ca@first@l | |
\pgfmathsetlengthmacro\forest@calign@anchor{% | |
-tan(\forestove{calign primary angle})*(\forest@ca@first@l+\forest@ca@parent@anchor@l-\forest@temp@child@anchor@l)% | |
+\forest@ca@first@child@anchor@s-\forest@ca@parent@anchor@s | |
}% | |
\fi | |
\fi | |
\forest@calign@s@shift{-\forest@calign@anchor}% | |
} | |
\def\forest@node@getedge#1#2#3{% | |
\forestoget{#1@edge@#2}#3% | |
\ifx#3\relax | |
\forest@node@foreachchild{% | |
\forest@node@getedge{#1}{#2}{\forest@temp@edge}% | |
}% | |
\forest@forthis{\forest@node@getedges{#2}}% | |
\forestoget{#1@edge@#2}#3% | |
\fi | |
} | |
\def\forest@node@getedges#1{% | |
%{% | |
\forest@setupgrowline{#1}% | |
\ifnum\forestove{ignore}=0 | |
\forestoget{boundary}\forest@node@boundary | |
\else | |
\def\forest@node@boundary{}% | |
\fi | |
\csname forest@getboth\forestove{fit}edgesofpath\endcsname | |
\forest@node@boundary\forest@negative@node@edge\forest@positive@node@edge | |
\forestolet{negative@edge@#1}\forest@negative@node@edge | |
\forestolet{positive@edge@#1}\forest@positive@node@edge | |
\get@edges@merge{negative}{#1}% | |
\get@edges@merge{positive}{#1}% | |
%}% | |
} | |
\def\get@edges@merge#1#2{% | |
\ifnum\forestove{n children}>0 | |
\forestoget{#1@edge@#2}\forest@node@edge | |
\forestove{parent@anchor}% | |
\edef\forest@getedge@pa@l{\the\pgf@x}% | |
\edef\forest@getedge@pa@s{\the\pgf@y}% | |
\eappto\forest@node@edge{\noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@pa@l}{\forest@getedge@pa@s}}% | |
\pgftransformreset | |
\pgftransformrotate{\forestove{grow}}% | |
\def\forest@all@edges{}% | |
\forest@node@foreachchild{% | |
\forestoget{#1@edge@#2}\forest@temp@edge | |
\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% | |
\forest@extendpath\forest@node@edge\forest@temp@edge{}% | |
\ifnum\forestove{ignore edge}=0 | |
\pgfpointadd | |
{\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}}% | |
{\forestove{child@anchor}}% | |
\pgfgetlastxy{\forest@getedge@ca@l}{\forest@getedge@ca@s}% | |
\eappto\forest@all@edges{% | |
\noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@pa@l}{\forest@getedge@pa@s}% | |
\noexpand\pgfsyssoftpath@linetotoken{\forest@getedge@ca@l}{\forest@getedge@ca@s}% | |
}% | |
% this deals with potential overlap of the edges: | |
\eappto\forest@node@edge{\noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@ca@l}{\forest@getedge@ca@s}}% | |
\fi | |
}% | |
\ifdefempty{\forest@all@edges}{}{% | |
\pgfintersectionofpaths{\pgfsetpath\forest@all@edges}{\pgfsetpath\forest@node@edge}% | |
\def\forest@edgenode@intersections{}% | |
\forest@merge@intersectionloop | |
\eappto\forest@node@edge{\expandonce{\forest@all@edges}\expandonce{\forest@edgenode@intersections}}% | |
}% | |
\csname forest@get#1\forestove{fit}edgeofpath\endcsname\forest@node@edge\forest@node@edge | |
\forestolet{#1@edge@#2}\forest@node@edge | |
\fi | |
} | |
\newloop\forest@merge@loop | |
\def\forest@merge@intersectionloop{% | |
\c@pgf@counta=0 | |
\forest@merge@loop | |
\ifnum\c@pgf@counta<\pgfintersectionsolutions\relax | |
\advance\c@pgf@counta1 | |
\pgfpointintersectionsolution{\the\c@pgf@counta}% | |
\eappto\forest@edgenode@intersections{\noexpand\pgfsyssoftpath@movetotoken | |
{\the\pgf@x}{\the\pgf@y}}% | |
\forest@merge@repeat | |
} | |
\def\forest@node@getboundingrectangle@ls#1{% | |
\forestoget{boundary}\forest@node@boundary | |
\forest@path@getboundingrectangle@ls\forest@node@boundary{#1}% | |
} | |
\def\forest@pgfpathtransformed#1{% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@pgfpathtransformed@moveto | |
\let\pgfsyssoftpath@linetotoken\forest@pgfpathtransformed@lineto | |
\pgfsyssoftpath@setcurrentpath\pgfutil@empty | |
#1% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
} | |
\def\forest@pgfpathtransformed@moveto#1#2{% | |
\forest@pgfpathtransformed@op\pgfsyssoftpath@moveto{#1}{#2}% | |
} | |
\def\forest@pgfpathtransformed@lineto#1#2{% | |
\forest@pgfpathtransformed@op\pgfsyssoftpath@lineto{#1}{#2}% | |
} | |
\def\forest@pgfpathtransformed@op#1#2#3{% | |
\pgfpointtransformed{\pgfqpoint{#2}{#3}}% | |
\edef\forest@temp{% | |
\noexpand#1{\the\pgf@x}{\the\pgf@y}% | |
}% | |
\forest@temp | |
} | |
\def\forest@pack@computetiers{% | |
{% | |
\forest@pack@tiers@getalltiersinsubtree | |
\forest@pack@tiers@computetierhierarchy | |
\forest@pack@tiers@findcontainers | |
\forest@pack@tiers@raisecontainers | |
\forest@pack@tiers@computeprocessingorder | |
\gdef\forest@smuggle{}% | |
\forest@pack@tiers@write | |
}% | |
\forest@node@foreach{\forestoset{@tiers}{}}% | |
\forest@smuggle | |
} | |
\def\forest@pack@tiers@getalltiersinsubtree{% | |
\ifnum\forestove{n children}>0 | |
\forest@node@foreachchild{\forest@pack@tiers@getalltiersinsubtree}% | |
\fi | |
\forestoget{tier}\forest@temp@mytier | |
\def\forest@temp@mytiers{}% | |
\ifdefempty\forest@temp@mytier{}{% | |
\listeadd\forest@temp@mytiers\forest@temp@mytier | |
}% | |
\ifnum\forestove{n children}>0 | |
\forest@node@foreachchild{% | |
\forestoget{tiers}\forest@temp@tiers | |
\forlistloop\forest@pack@tiers@forhandlerA\forest@temp@tiers | |
}% | |
\fi | |
\forestolet{tiers}\forest@temp@mytiers | |
} | |
\def\forest@pack@tiers@forhandlerA#1{% | |
\ifinlist{#1}\forest@temp@mytiers{}{% | |
\listeadd\forest@temp@mytiers{#1}% | |
}% | |
} | |
\def\forest@pack@tiers@computetierhierarchy{% | |
\def\forest@tiers@ancestors{}% | |
\forestoget{tiers}\forest@temp@mytiers | |
\forlistloop\forest@pack@tiers@cth@init\forest@temp@mytiers | |
\forest@pack@tiers@computetierhierarchy@ | |
} | |
\def\forest@pack@tiers@cth@init#1{% | |
\csdef{forest@tiers@higher@#1}{}% | |
\csdef{forest@tiers@lower@#1}{}% | |
} | |
\def\forest@pack@tiers@computetierhierarchy@{% | |
\forestoget{tier}\forest@temp@mytier | |
\ifdefempty\forest@temp@mytier{}{% | |
\forlistloop\forest@pack@tiers@forhandlerB\forest@tiers@ancestors | |
\listeadd\forest@tiers@ancestors\forest@temp@mytier | |
}% | |
\forest@node@foreachchild{% | |
\forest@pack@tiers@computetierhierarchy@ | |
}% | |
\forestoget{tier}\forest@temp@mytier | |
\ifdefempty\forest@temp@mytier{}{% | |
\forest@listedel\forest@tiers@ancestors\forest@temp@mytier | |
}% | |
} | |
\def\forest@pack@tiers@forhandlerB#1{% | |
\def\forest@temp@tier{#1}% | |
\ifx\forest@temp@tier\forest@temp@mytier | |
\PackageError{forest}{Circular tier hierarchy (tier \forest@temp@mytier)}{}% | |
\fi | |
\ifinlistcs{#1}{forest@tiers@higher@\forest@temp@mytier}{}{% | |
\listcsadd{forest@tiers@higher@\forest@temp@mytier}{#1}}% | |
\xifinlistcs\forest@temp@mytier{forest@tiers@lower@#1}{}{% | |
\listcseadd{forest@tiers@lower@#1}{\forest@temp@mytier}}% | |
} | |
\def\forest@pack@tiers@findcontainers{% | |
\forestoget{tiers}\forest@temp@tiers | |
\forlistloop\forest@pack@tiers@findcontainer\forest@temp@tiers | |
} | |
\def\forest@pack@tiers@findcontainer#1{% | |
\def\forest@temp@tier{#1}% | |
\forestoget{tier}\forest@temp@mytier | |
\ifx\forest@temp@tier\forest@temp@mytier | |
\csedef{forest@tiers@container@#1}{\forest@cn}% | |
\else\@escapeif{% | |
\forest@pack@tiers@findcontainerA{#1}% | |
}\fi% | |
} | |
\def\forest@pack@tiers@findcontainerA#1{% | |
\c@pgf@counta=0 | |
\forest@node@foreachchild{% | |
\forestoget{tiers}\forest@temp@tiers | |
\ifinlist{#1}\forest@temp@tiers{% | |
\advance\c@pgf@counta 1 | |
\let\forest@temp@child\forest@cn | |
}{}% | |
}% | |
\ifnum\c@pgf@counta>1 | |
\csedef{forest@tiers@container@#1}{\forest@cn}% | |
\else\@escapeif{% surely =1 | |
\forest@fornode{\forest@temp@child}{% | |
\forest@pack@tiers@findcontainer{#1}% | |
}% | |
}\fi | |
} | |
\def\forest@pack@tiers@raisecontainers{% | |
\forestoget{tiers}\forest@temp@mytiers | |
\forlistloop\forest@pack@tiers@rc@forhandlerA\forest@temp@mytiers | |
} | |
\def\forest@pack@tiers@rc@forhandlerA#1{% | |
\edef\forest@tiers@temptier{#1}% | |
\letcs\forest@tiers@containernodeoftier{forest@tiers@container@#1}% | |
\letcs\forest@temp@lowertiers{forest@tiers@lower@#1}% | |
\forlistloop\forest@pack@tiers@rc@forhandlerB\forest@temp@lowertiers | |
} | |
\def\forest@pack@tiers@rc@forhandlerB#1{% | |
\letcs\forest@tiers@containernodeoflowertier{forest@tiers@container@#1}% | |
\forestOget{\forest@tiers@containernodeoflowertier}{content}\lowercontent | |
\forestOget{\forest@tiers@containernodeoftier}{content}\uppercontent | |
\forest@fornode{\forest@tiers@containernodeoflowertier}{% | |
\forest@ifancestorof | |
{\forest@tiers@containernodeoftier} | |
{\csletcs{forest@tiers@container@\forest@tiers@temptier}{forest@tiers@container@#1}}% | |
{}% | |
}% | |
} | |
\def\forest@pack@tiers@computeprocessingorder{% | |
\def\forest@tiers@processingorder{}% | |
\forestoget{tiers}\forest@tiers@cpo@tierstodo | |
\forest@loopa | |
\ifdefempty\forest@tiers@cpo@tierstodo{\forest@tempfalse}{\forest@temptrue}% | |
\ifforest@temp | |
\def\forest@tiers@cpo@tiersremaining{}% | |
\def\forest@tiers@cpo@tiersindependent{}% | |
\forlistloop\forest@pack@tiers@cpo@forhandlerA\forest@tiers@cpo@tierstodo | |
\ifdefempty\forest@tiers@cpo@tiersindependent{% | |
\PackageError{forest}{Circular tiers!}{}}{}% | |
\forlistloop\forest@pack@tiers@cpo@forhandlerB\forest@tiers@cpo@tiersremaining | |
\let\forest@tiers@cpo@tierstodo\forest@tiers@cpo@tiersremaining | |
\forest@repeata | |
} | |
\def\forest@pack@tiers@cpo@forhandlerA#1{% | |
\ifcsempty{forest@tiers@higher@#1}{% | |
\listadd\forest@tiers@cpo@tiersindependent{#1}% | |
\listadd\forest@tiers@processingorder{#1}% | |
}{% | |
\listadd\forest@tiers@cpo@tiersremaining{#1}% | |
}% | |
} | |
\def\forest@pack@tiers@cpo@forhandlerB#1{% | |
\def\forest@pack@tiers@cpo@aremainingtier{#1}% | |
\forlistloop\forest@pack@tiers@cpo@forhandlerC\forest@tiers@cpo@tiersindependent | |
} | |
\def\forest@pack@tiers@cpo@forhandlerC#1{% | |
\ifinlistcs{#1}{forest@tiers@higher@\forest@pack@tiers@cpo@aremainingtier}{% | |
\forest@listcsdel{forest@tiers@higher@\forest@pack@tiers@cpo@aremainingtier}{#1}% | |
}{}% | |
} | |
\def\forest@pack@tiers@write{% | |
\forlistloop\forest@pack@tiers@write@forhandler\forest@tiers@processingorder | |
} | |
\def\forest@pack@tiers@write@forhandler#1{% | |
\forest@fornode{\csname forest@tiers@container@#1\endcsname}{% | |
\forest@pack@tiers@check{#1}% | |
}% | |
\xappto\forest@smuggle{% | |
\noexpand\listadd | |
\forestOm{\csname forest@tiers@container@#1\endcsname}{@tiers}% | |
{#1}% | |
}% | |
} | |
% checks if the tier is compatible with growth changes and calign=node/edge angle | |
\def\forest@pack@tiers@check#1{% | |
\def\forest@temp@currenttier{#1}% | |
\forest@node@foreachdescendant{% | |
\ifnum\forestove{grow}=\forestOve{\forestove{@parent}}{grow} | |
\else | |
\forest@pack@tiers@check@grow | |
\fi | |
\ifnum\forestove{n children}>1 | |
\forestoget{calign}\forest@temp | |
\ifx\forest@temp\forest@pack@tiers@check@nodeangle | |
\forest@pack@tiers@check@calign | |
\fi | |
\ifx\forest@temp\forest@pack@tiers@check@edgeangle | |
\forest@pack@tiers@check@calign | |
\fi | |
\fi | |
}% | |
} | |
\def\forest@pack@tiers@check@nodeangle{node angle}% | |
\def\forest@pack@tiers@check@edgeangle{edge angle}% | |
\def\forest@pack@tiers@check@grow{% | |
\forestoget{content}\forest@temp@content | |
\let\forest@temp@currentnode\forest@cn | |
\forest@node@foreachdescendant{% | |
\forestoget{tier}\forest@temp | |
\ifx\forest@temp@currenttier\forest@temp | |
\forest@pack@tiers@check@grow@error | |
\fi | |
}% | |
} | |
\def\forest@pack@tiers@check@grow@error{% | |
\PackageError{forest}{Tree growth direction changes in node \forest@temp@currentnode\space | |
(content: \forest@temp@content), while tier '\forest@temp' is specified for nodes both | |
out- and inside the subtree rooted in node \forest@temp@currentnode. This will not work.}{}% | |
} | |
\def\forest@pack@tiers@check@calign{% | |
\forest@node@foreachchild{% | |
\forestoget{tier}\forest@temp | |
\ifx\forest@temp@currenttier\forest@temp | |
\forest@pack@tiers@check@calign@warning | |
\fi | |
}% | |
} | |
\def\forest@pack@tiers@check@calign@warning{% | |
\PackageWarning{forest}{Potential option conflict: node \forestove{@parent} (content: | |
'\forestOve{\forestove{@parent}}{content}') was given 'calign=\forestove{calign}', while its | |
child \forest@cn\space (content: '\forestove{content}') was given 'tier=\forestove{tier}'. | |
The parent's 'calign' will only work if the child was the lowest node on its tier before the | |
alignment.}{} | |
} | |
\pgfdeclaregenericanchor{forestcomputenodeboundary}{% | |
\letcs\forest@temp@boundary@macro{forest@compute@node@boundary@#1}% | |
\ifcsname forest@compute@node@boundary@#1\endcsname | |
\csname forest@compute@node@boundary@#1\endcsname | |
\else | |
\forest@compute@node@boundary@rectangle | |
\fi | |
\pgfsyssoftpath@getcurrentpath\forest@temp | |
\global\let\forest@global@boundary\forest@temp | |
} | |
\def\forest@mt#1{% | |
\expandafter\pgfpointanchor\expandafter{\pgfreferencednodename}{#1}% | |
\pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}% | |
}% | |
\def\forest@lt#1{% | |
\expandafter\pgfpointanchor\expandafter{\pgfreferencednodename}{#1}% | |
\pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% | |
}% | |
\def\forest@compute@node@boundary@coordinate{% | |
\forest@mt{center}% | |
} | |
\def\forest@compute@node@boundary@circle{% | |
\forest@mt{east}% | |
\forest@lt{north east}% | |
\forest@lt{north}% | |
\forest@lt{north west}% | |
\forest@lt{west}% | |
\forest@lt{south west}% | |
\forest@lt{south}% | |
\forest@lt{south east}% | |
\forest@lt{east}% | |
} | |
\def\forest@compute@node@boundary@rectangle{% | |
\forest@mt{south west}% | |
\forest@lt{south east}% | |
\forest@lt{north east}% | |
\forest@lt{north west}% | |
\forest@lt{south west}% | |
} | |
\def\forest@compute@node@boundary@diamond{% | |
\forest@mt{east}% | |
\forest@lt{north}% | |
\forest@lt{west}% | |
\forest@lt{south}% | |
\forest@lt{east}% | |
} | |
\let\forest@compute@node@boundary@ellipse\forest@compute@node@boundary@circle | |
\def\forest@compute@node@boundary@trapezium{% | |
\forest@mt{top right corner}% | |
\forest@lt{top left corner}% | |
\forest@lt{bottom left corner}% | |
\forest@lt{bottom right corner}% | |
\forest@lt{top right corner}% | |
} | |
\def\forest@compute@node@boundary@semicircle{% | |
\forest@mt{arc start}% | |
\forest@lt{north}% | |
\forest@lt{east}% | |
\forest@lt{north east}% | |
\forest@lt{apex}% | |
\forest@lt{north west}% | |
\forest@lt{west}% | |
\forest@lt{arc end}% | |
\forest@lt{arc start}% | |
} | |
\newloop\forest@computenodeboundary@loop | |
\csdef{forest@compute@node@boundary@regular polygon}{% | |
\forest@mt{corner 1}% | |
\c@pgf@counta=\sides\relax | |
\forest@computenodeboundary@loop | |
\ifnum\c@pgf@counta>0 | |
\forest@lt{corner \the\c@pgf@counta}% | |
\advance\c@pgf@counta-1 | |
\forest@computenodeboundary@repeat | |
}% | |
\def\forest@compute@node@boundary@star{% | |
\forest@mt{outer point 1}% | |
\c@pgf@counta=\totalstarpoints\relax | |
\divide\c@pgf@counta2 | |
\forest@computenodeboundary@loop | |
\ifnum\c@pgf@counta>0 | |
\forest@lt{inner point \the\c@pgf@counta}% | |
\forest@lt{outer point \the\c@pgf@counta}% | |
\advance\c@pgf@counta-1 | |
\forest@computenodeboundary@repeat | |
}% | |
\csdef{forest@compute@node@boundary@isosceles triangle}{% | |
\forest@mt{apex}% | |
\forest@lt{left corner}% | |
\forest@lt{right corner}% | |
\forest@lt{apex}% | |
} | |
\def\forest@compute@node@boundary@kite{% | |
\forest@mt{upper vertex}% | |
\forest@lt{left vertex}% | |
\forest@lt{lower vertex}% | |
\forest@lt{right vertex}% | |
\forest@lt{upper vertex}% | |
} | |
\def\forest@compute@node@boundary@dart{% | |
\forest@mt{tip}% | |
\forest@lt{left tail}% | |
\forest@lt{tail center}% | |
\forest@lt{right tail}% | |
\forest@lt{tip}% | |
} | |
\csdef{forest@compute@node@boundary@circular sector}{% | |
\forest@mt{sector center}% | |
\forest@lt{arc start}% | |
\forest@lt{arc center}% | |
\forest@lt{arc end}% | |
\forest@lt{sector center}% | |
} | |
\def\forest@compute@node@boundary@cylinder{% | |
\forest@mt{top}% | |
\forest@lt{after top}% | |
\forest@lt{before bottom}% | |
\forest@lt{bottom}% | |
\forest@lt{after bottom}% | |
\forest@lt{before top}% | |
\forest@lt{top}% | |
} | |
\cslet{forest@compute@node@boundary@forbidden sign}\forest@compute@node@boundary@circle | |
\cslet{forest@compute@node@boundary@magnifying glass}\forest@compute@node@boundary@circle | |
\def\forest@compute@node@boundary@cloud{% | |
\getradii | |
\forest@mt{puff 1}% | |
\c@pgf@counta=\puffs\relax | |
\forest@computenodeboundary@loop | |
\ifnum\c@pgf@counta>0 | |
\forest@lt{puff \the\c@pgf@counta}% | |
\advance\c@pgf@counta-1 | |
\forest@computenodeboundary@repeat | |
} | |
\def\forest@compute@node@boundary@starburst{ | |
\calculatestarburstpoints | |
\forest@mt{outer point 1}% | |
\c@pgf@counta=\totalpoints\relax | |
\divide\c@pgf@counta2 | |
\forest@computenodeboundary@loop | |
\ifnum\c@pgf@counta>0 | |
\forest@lt{inner point \the\c@pgf@counta}% | |
\forest@lt{outer point \the\c@pgf@counta}% | |
\advance\c@pgf@counta-1 | |
\forest@computenodeboundary@repeat | |
}% | |
\def\forest@compute@node@boundary@signal{% | |
\forest@mt{east}% | |
\forest@lt{south east}% | |
\forest@lt{south west}% | |
\forest@lt{west}% | |
\forest@lt{north west}% | |
\forest@lt{north east}% | |
\forest@lt{east}% | |
} | |
\def\forest@compute@node@boundary@tape{% | |
\forest@mt{north east}% | |
\forest@lt{60}% | |
\forest@lt{north}% | |
\forest@lt{120}% | |
\forest@lt{north west}% | |
\forest@lt{south west}% | |
\forest@lt{240}% | |
\forest@lt{south}% | |
\forest@lt{310}% | |
\forest@lt{south east}% | |
\forest@lt{north east}% | |
} | |
\csdef{forest@compute@node@boundary@single arrow}{% | |
\forest@mt{tip}% | |
\forest@lt{after tip}% | |
\forest@lt{after head}% | |
\forest@lt{before tail}% | |
\forest@lt{after tail}% | |
\forest@lt{before head}% | |
\forest@lt{before tip}% | |
\forest@lt{tip}% | |
} | |
\csdef{forest@compute@node@boundary@double arrow}{% | |
\forest@mt{tip 1}% | |
\forest@lt{after tip 1}% | |
\forest@lt{after head 1}% | |
\forest@lt{before head 2}% | |
\forest@lt{before tip 2}% | |
\forest@mt{tip 2}% | |
\forest@lt{after tip 2}% | |
\forest@lt{after head 2}% | |
\forest@lt{before head 1}% | |
\forest@lt{before tip 1}% | |
\forest@lt{tip 1}% | |
} | |
\csdef{forest@compute@node@boundary@arrow box}{% | |
\forest@mt{before north arrow}% | |
\forest@lt{before north arrow head}% | |
\forest@lt{before north arrow tip}% | |
\forest@lt{north arrow tip}% | |
\forest@lt{after north arrow tip}% | |
\forest@lt{after north arrow head}% | |
\forest@lt{after north arrow}% | |
\forest@lt{north east}% | |
\forest@lt{before east arrow}% | |
\forest@lt{before east arrow head}% | |
\forest@lt{before east arrow tip}% | |
\forest@lt{east arrow tip}% | |
\forest@lt{after east arrow tip}% | |
\forest@lt{after east arrow head}% | |
\forest@lt{after east arrow}% | |
\forest@lt{south east}% | |
\forest@lt{before south arrow}% | |
\forest@lt{before south arrow head}% | |
\forest@lt{before south arrow tip}% | |
\forest@lt{south arrow tip}% | |
\forest@lt{after south arrow tip}% | |
\forest@lt{after south arrow head}% | |
\forest@lt{after south arrow}% | |
\forest@lt{south west}% | |
\forest@lt{before west arrow}% | |
\forest@lt{before west arrow head}% | |
\forest@lt{before west arrow tip}% | |
\forest@lt{west arrow tip}% | |
\forest@lt{after west arrow tip}% | |
\forest@lt{after west arrow head}% | |
\forest@lt{after west arrow}% | |
\forest@lt{north west}% | |
\forest@lt{before north arrow}% | |
} | |
\cslet{forest@compute@node@boundary@circle split}\forest@compute@node@boundary@circle | |
\cslet{forest@compute@node@boundary@circle solidus}\forest@compute@node@boundary@circle | |
\cslet{forest@compute@node@boundary@ellipse split}\forest@compute@node@boundary@ellipse | |
\cslet{forest@compute@node@boundary@rectangle split}\forest@compute@node@boundary@rectangle | |
\def\forest@compute@node@boundary@@callout{% | |
\beforecalloutpointer | |
\pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}% | |
\calloutpointeranchor | |
\pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% | |
\aftercalloutpointer | |
\pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% | |
} | |
\csdef{forest@compute@node@boundary@rectangle callout}{% | |
\forest@compute@node@boundary@rectangle | |
\rectanglecalloutpoints | |
\forest@compute@node@boundary@@callout | |
} | |
\csdef{forest@compute@node@boundary@ellipse callout}{% | |
\forest@compute@node@boundary@ellipse | |
\ellipsecalloutpoints | |
\forest@compute@node@boundary@@callout | |
} | |
\csdef{forest@compute@node@boundary@cloud callout}{% | |
\forest@compute@node@boundary@cloud | |
% at least a first approx... | |
\forest@mt{center}% | |
\forest@lt{pointer}% | |
}% | |
\csdef{forest@compute@node@boundary@cross out}{% | |
\forest@mt{south east}% | |
\forest@lt{north west}% | |
\forest@mt{south west}% | |
\forest@lt{north east}% | |
}% | |
\csdef{forest@compute@node@boundary@strike out}{% | |
\forest@mt{north east}% | |
\forest@lt{south west}% | |
}% | |
\cslet{forest@compute@node@boundary@rounded rectangle}\forest@compute@node@boundary@rectangle | |
\csdef{forest@compute@node@boundary@chamfered rectangle}{% | |
\forest@mt{before south west}% | |
\forest@mt{after south west}% | |
\forest@lt{before south east}% | |
\forest@lt{after south east}% | |
\forest@lt{before north east}% | |
\forest@lt{after north east}% | |
\forest@lt{before north west}% | |
\forest@lt{after north west}% | |
\forest@lt{before south west}% | |
}% | |
\def\forest@node@computeabsolutepositions{% | |
\forestoset{x}{0pt}% | |
\forestoset{y}{0pt}% | |
\edef\forest@marshal{% | |
\noexpand\forest@node@foreachchild{% | |
\noexpand\forest@node@computeabsolutepositions@{0pt}{0pt}{\forestove{grow}}% | |
}% | |
}\forest@marshal | |
} | |
\def\forest@node@computeabsolutepositions@#1#2#3{% | |
\pgfpointadd{\pgfpoint{#1}{#2}}{% | |
\pgfpointadd{\pgfpolar{#3}{\forestove{l}}}{\pgfpolar{90 + #3}{\forestove{s}}}}% | |
\pgfgetlastxy\forest@temp@x\forest@temp@y | |
\forestolet{x}\forest@temp@x | |
\forestolet{y}\forest@temp@y | |
\edef\forest@marshal{% | |
\noexpand\forest@node@foreachchild{% | |
\noexpand\forest@node@computeabsolutepositions@{\forest@temp@x}{\forest@temp@y}{\forestove{grow}}% | |
}% | |
}\forest@marshal | |
} | |
\newif\ifforest@drawtree@preservenodeboxes@ | |
\def\forest@node@drawtree{% | |
\expandafter\ifstrequal\expandafter{\forest@drawtreebox}{\pgfkeysnovalue}{% | |
\let\forest@drawtree@beginbox\relax | |
\let\forest@drawtree@endbox\relax | |
}{% | |
\edef\forest@drawtree@beginbox{\global\setbox\forest@drawtreebox=\hbox\bgroup}% | |
\let\forest@drawtree@endbox\egroup | |
}% | |
\ifforest@external@ | |
\ifforest@externalize@tree@ | |
\forest@temptrue | |
\else | |
\tikzifexternalizing{% | |
\ifforest@was@tikzexternalwasenable | |
\forest@temptrue | |
\pgfkeys{/tikz/external/optimize=false}% | |
\let\forest@drawtree@beginbox\relax | |
\let\forest@drawtree@endbox\relax | |
\else | |
\forest@tempfalse | |
\fi | |
}{% | |
\forest@tempfalse | |
}% | |
\fi | |
\ifforest@temp | |
\advance\forest@externalize@inner@n 1 | |
\edef\forest@externalize@filename{% | |
\tikzexternalrealjob-forest-\forest@externalize@outer@n | |
\ifnum\forest@externalize@inner@n=0 \else.\the\forest@externalize@inner@n\fi}% | |
\expandafter\tikzsetnextfilename\expandafter{\forest@externalize@filename}% | |
\tikzexternalenable | |
\pgfkeysalso{/tikz/external/remake next,/tikz/external/export next}% | |
\fi | |
\ifforest@externalize@tree@ | |
\typeout{forest: Invoking a recursive call to generate the external picture | |
'\forest@externalize@filename' for the following context+code: | |
'\expandafter\detokenize\expandafter{\forest@externalize@id}'}% | |
\fi | |
\fi | |
% | |
\ifforesttikzcshack | |
\let\forest@original@tikz@parse@node\tikz@parse@node | |
\let\tikz@parse@node\forest@tikz@parse@node | |
\fi | |
\forest@drawtree@beginbox | |
%\pgfkeysalso{/forest/begin draw}% | |
\begin{tikzpicture} | |
\forest@node@drawtree@ | |
%\pgfkeysalso{/forest/end draw}% | |
\end{tikzpicture} | |
\forest@drawtree@endbox | |
\ifforesttikzcshack | |
\let\tikz@parse@node\forest@original@tikz@parse@node | |
\fi | |
% | |
\ifforest@external@ | |
\ifforest@externalize@tree@ | |
\tikzexternaldisable | |
\eappto\forest@externalize@checkimages{% | |
\noexpand\forest@includeexternal@check{\forest@externalize@filename}% | |
}% | |
\expandafter\ifstrequal\expandafter{\forest@drawtreebox}{\pgfkeysnovalue}{% | |
\eappto\forest@externalize@loadimages{% | |
\noexpand\forest@includeexternal{\forest@externalize@filename}% | |
}% | |
}{% | |
\eappto\forest@externalize@loadimages{% | |
\noexpand\forest@includeexternal@box\forest@drawtreebox{\forest@externalize@filename}% | |
}% | |
}% | |
\fi | |
\fi | |
} | |
\def\forest@node@drawtree@{% | |
\forest@node@foreach{\forest@draw@node}% | |
\forest@node@Ifnamedefined{forest@baseline@node}{% | |
\edef\forest@temp{% | |
\noexpand\pgfsetbaselinepointlater{% | |
\noexpand\pgfpointanchor | |
{\forestOve{\forest@node@Nametoid{forest@baseline@node}}{name}} | |
{\forestOve{\forest@node@Nametoid{forest@baseline@node}}{anchor}} | |
}% | |
}\forest@temp | |
}{}% | |
\forest@node@foreachdescendant{\forest@draw@edge}% | |
\forest@node@foreach{\forest@draw@tikz}% | |
} | |
\def\forest@draw@node{% | |
\ifnum\forestove{phantom}=0 | |
\forest@node@forest@positionnodelater@restore | |
\ifforest@drawtree@preservenodeboxes@ | |
\pgfnodealias{forest@temp}{\forestove{later@name}}% | |
\fi | |
\pgfpositionnodenow{\pgfqpoint{\forestove{x}}{\forestove{y}}}% | |
\ifforest@drawtree@preservenodeboxes@ | |
\pgfnodealias{\forestove{later@name}}{forest@temp}% | |
\fi | |
\fi | |
} | |
\def\forest@draw@edge{% | |
\ifnum\forestove{phantom}=0 | |
\ifnum\forestOve{\forestove{@parent}}{phantom}=0 | |
\edef\forest@temp{\forestove{edge path}}% | |
\forest@temp | |
\fi | |
\fi | |
} | |
\def\forest@draw@tikz{% | |
\forestove{tikz}% | |
} | |
\def\forest@tikz@parse@node#1(#2){% | |
\pgfutil@in@.{#2}% | |
\ifpgfutil@in@ | |
\expandafter\forest@tikz@parse@node@checkiftikzname@withdot | |
\else% | |
\expandafter\forest@tikz@parse@node@checkiftikzname@withoutdot | |
\fi% | |
#1(#2)\forest@end | |
} | |
\def\forest@tikz@parse@node@checkiftikzname@withdot#1(#2.#3)\forest@end{% | |
\forest@tikz@parse@node@checkiftikzname#1{#2}{.#3}} | |
\def\forest@tikz@parse@node@checkiftikzname@withoutdot#1(#2)\forest@end{% | |
\forest@tikz@parse@node@checkiftikzname#1{#2}{}} | |
\def\forest@tikz@parse@node@checkiftikzname#1#2#3{% | |
\expandafter\ifx\csname pgf@sh@ns@#2\endcsname\relax | |
\forest@forthis{% | |
\forest@nameandgo{#2}% | |
\edef\forest@temp@relativenodename{\forestove{name}}% | |
}% | |
\else | |
\def\forest@temp@relativenodename{#2}% | |
\fi | |
\expandafter\forest@original@tikz@parse@node\expandafter#1\expandafter(\forest@temp@relativenodename#3)% | |
} | |
\def\forest@nameandgo#1{% | |
\pgfutil@in@!{#1}% | |
\ifpgfutil@in@ | |
\forest@nameandgo@(#1)% | |
\else | |
\ifstrempty{#1}{}{\edef\forest@cn{\forest@node@Nametoid{#1}}}% | |
\fi | |
} | |
\def\forest@nameandgo@(#1!#2){% | |
\ifstrempty{#1}{}{\edef\forest@cn{\forest@node@Nametoid{#1}}}% | |
\forest@go{#2}% | |
} | |
\pgfdeclaregenericanchor{parent anchor}{% | |
\forest@generic@parent@child@anchor{parent }{#1}} | |
\pgfdeclaregenericanchor{child anchor}{% | |
\forest@generic@parent@child@anchor{child }{#1}} | |
\pgfdeclaregenericanchor{anchor}{% | |
\forest@generic@parent@child@anchor{}{#1}} | |
\def\forest@generic@parent@child@anchor#1#2{% | |
\forestOget{\forest@node@Nametoid{\pgfreferencednodename}}{#1anchor}\forest@temp@parent@anchor | |
\ifdefempty\forest@temp@parent@anchor{% | |
\pgf@sh@reanchor{#2}{center}% | |
\xdef\forest@hack@tikzshapeborder{% | |
\noexpand\tikz@shapebordertrue | |
\def\noexpand\tikz@shapeborder@name{\pgfreferencednodename}% | |
}\aftergroup\forest@hack@tikzshapeborder | |
}{% | |
\pgf@sh@reanchor{#2}{\forest@temp@parent@anchor}% | |
}% | |
} | |
\newdimen\forest@xg | |
\newdimen\forest@yg | |
\newdimen\forest@xs | |
\newdimen\forest@ys | |
\def\forest@setupgrowline#1{% | |
\edef\forest@grow{#1}% | |
\pgfpointpolar\forest@grow{1pt}% | |
\forest@xg=\pgf@x | |
\forest@yg=\pgf@y | |
\forest@xs=-\pgf@y | |
\forest@ys=\pgf@x | |
} | |
\def\forest@pgfpointprojectiontogrowline#1{{% | |
\pgf@process{#1}% | |
\pgfutil@tempdima=\pgf@sys@tonumber{\pgf@x}\forest@xg% | |
\advance\pgfutil@tempdima by\pgf@sys@tonumber{\pgf@y}\forest@yg% | |
\global\pgf@x=\pgf@sys@tonumber{\pgfutil@tempdima}\forest@xg% | |
\global\pgf@y=\pgf@sys@tonumber{\pgfutil@tempdima}\forest@yg% | |
}} | |
\def\forest@distancetogrowline#1#2{% | |
\pgf@process{#2}% | |
#1=\pgf@sys@tonumber{\pgf@x}\forest@xs\relax | |
\advance#1 by\pgf@sys@tonumber{\pgf@y}\forest@ys\relax | |
} | |
\let\forest@pp@n\relax | |
\def\forest@projectpathtogrowline#1#2{% | |
\edef\forest@pp@prefix{#2}% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@projectpath@processpoint | |
\let\pgfsyssoftpath@linetotoken\forest@projectpath@processpoint | |
\c@pgf@counta=0 | |
#1% | |
\csedef{#2n}{\the\c@pgf@counta}% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
} | |
\def\forest@projectpath@processpoint#1#2{% | |
\pgfqpoint{#1}{#2}% | |
\expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta xo\endcsname{\the\pgf@x}% | |
\expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta yo\endcsname{\the\pgf@y}% | |
\forest@pgfpointprojectiontogrowline{}% | |
\expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta xp\endcsname{\the\pgf@x}% | |
\expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta yp\endcsname{\the\pgf@y}% | |
\advance\c@pgf@counta 1\relax | |
} | |
\def\forest@sortprojections#1{% | |
% todo: optimize in cases when we know that the array is actually a | |
% merger of sorted arrays; when does this happen? in | |
% distance_between_paths, and when merging the edges of the parent | |
% and its children in a uniform growth tree | |
\edef\forest@ppi@inputprefix{#1}% | |
\c@pgf@counta=\csname#1n\endcsname\relax | |
\advance\c@pgf@counta -1 | |
\forest@sort\forest@ppiraw@cmp\forest@ppiraw@let\forest@sort@ascending{0}{\the\c@pgf@counta}% | |
} | |
\def\forest@processprojectioninfo#1#2{% | |
\edef\forest@ppi@inputprefix{#1}% | |
\c@pgf@counta=0 | |
\c@pgf@countb=-1 | |
\loop | |
\ifnum\c@pgf@counta<\csname#1n\endcsname\relax | |
\letcs\forest@xo{#1\the\c@pgf@counta xo}% | |
\letcs\forest@yo{#1\the\c@pgf@counta yo}% | |
\letcs\forest@xp{#1\the\c@pgf@counta xp}% | |
\letcs\forest@yp{#1\the\c@pgf@counta yp}% | |
\ifnum\c@pgf@countb<0 | |
\forest@equaltotolerancefalse | |
\else | |
\forest@equaltotolerance | |
{\pgfqpoint\forest@xp\forest@yp}% | |
{\pgfqpoint | |
{\csname#2\the\c@pgf@countb x\endcsname}% | |
{\csname#2\the\c@pgf@countb y\endcsname}% | |
}% | |
\fi | |
\ifforest@equaltotolerance\else | |
\advance\c@pgf@countb 1 | |
\cslet{#2\the\c@pgf@countb x}\forest@xp | |
\cslet{#2\the\c@pgf@countb y}\forest@yp | |
\csdef{#2\the\c@pgf@countb @n}{0}% | |
\fi | |
% todo: this is ugly! | |
\ifdefined\forest@xo\ifx\forest@xo\relax\else | |
\ifdefined\forest@yo\ifx\forest@yo\relax\else | |
\forest@append@point@to@inner@array | |
\forest@xo\forest@yo | |
{#2\the\c@pgf@countb @}% | |
\csedef{#2(\forest@xo,\forest@yo)}{\the\c@pgf@countb}% | |
\fi\fi | |
\fi\fi | |
\cslet{#1\the\c@pgf@counta xo}\relax | |
\cslet{#1\the\c@pgf@counta yo}\relax | |
\cslet{#1\the\c@pgf@counta xp}\relax | |
\cslet{#1\the\c@pgf@counta yp}\relax | |
\advance\c@pgf@counta 1 | |
\repeat | |
\cslet{#1n}\relax | |
\advance\c@pgf@countb 1 | |
\csedef{#2n}{\the\c@pgf@countb}% | |
} | |
\def\forest@ppiraw@let#1#2{% | |
\csletcs{\forest@ppi@inputprefix#1xo}{\forest@ppi@inputprefix#2xo}% | |
\csletcs{\forest@ppi@inputprefix#1yo}{\forest@ppi@inputprefix#2yo}% | |
\csletcs{\forest@ppi@inputprefix#1xp}{\forest@ppi@inputprefix#2xp}% | |
\csletcs{\forest@ppi@inputprefix#1yp}{\forest@ppi@inputprefix#2yp}% | |
} | |
\def\forest@ppiraw@cmp#1#2{% | |
\forest@sort@cmptwodimcs | |
{\forest@ppi@inputprefix#1xp}{\forest@ppi@inputprefix#1yp}% | |
{\forest@ppi@inputprefix#2xp}{\forest@ppi@inputprefix#2yp}% | |
} | |
\def\forest@append@point@to@inner@array#1#2#3{% | |
\c@pgf@countc=\csname#3n\endcsname\relax | |
\csedef{#3\the\c@pgf@countc x}{#1}% | |
\csedef{#3\the\c@pgf@countc y}{#2}% | |
\forest@distancetogrowline\pgfutil@tempdima{\pgfqpoint#1#2}% | |
\csedef{#3\the\c@pgf@countc d}{\the\pgfutil@tempdima}% | |
\advance\c@pgf@countc 1 | |
\csedef{#3n}{\the\c@pgf@countc}% | |
} | |
\def\forest@breakpath#1#2#3{% | |
\edef\forest@bp@prefix{#2}% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@breakpath@processfirstpoint | |
\let\pgfsyssoftpath@linetotoken\forest@breakpath@processfirstpoint | |
%\pgfusepath{}% empty the current path. ok? | |
#1% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
\pgfsyssoftpath@getcurrentpath#3% | |
} | |
\def\forest@breakpath@processfirstpoint#1#2{% | |
\forest@breakpath@processmoveto{#1}{#2}% | |
\let\pgfsyssoftpath@movetotoken\forest@breakpath@processmoveto | |
\let\pgfsyssoftpath@linetotoken\forest@breakpath@processlineto | |
} | |
\def\forest@breakpath@processmoveto#1#2{% | |
\pgfsyssoftpath@moveto{#1}{#2}% | |
\def\forest@previous@x{#1}% | |
\def\forest@previous@y{#2}% | |
\expandafter\let\expandafter\forest@previous@i | |
\csname\forest@bp@prefix(#1,#2)\endcsname | |
\expandafter\let\expandafter\forest@previous@px | |
\csname\forest@bp@prefix\forest@previous@i x\endcsname | |
\expandafter\let\expandafter\forest@previous@py | |
\csname\forest@bp@prefix\forest@previous@i y\endcsname | |
} | |
\def\forest@breakpath@processlineto#1#2{% | |
\let\forest@breakpath@op\pgfsyssoftpath@lineto | |
\expandafter\let\expandafter\forest@i | |
\csname\forest@bp@prefix(#1,#2)\endcsname | |
\expandafter\let\expandafter\forest@px | |
\csname\forest@bp@prefix\forest@i x\endcsname | |
\expandafter\let\expandafter\forest@py | |
\csname\forest@bp@prefix\forest@i y\endcsname | |
\forest@equaltotolerance | |
{\pgfqpoint{\forest@previous@px}{\forest@previous@py}}% | |
{\pgfqpoint{\forest@px}{\forest@py}}% | |
\ifforest@equaltotolerance | |
\let\forest@breakpath@op\pgfsyssoftpath@moveto | |
\else | |
\forest@temp@count=\forest@previous@i\relax | |
\ifnum\forest@previous@i<\forest@i\relax | |
\def\forest@breakpath@step{1}% | |
\def\forest@breakpath@test{\forest@temp@count<\forest@i\relax}% | |
\else | |
\def\forest@breakpath@step{-1}% | |
\def\forest@breakpath@test{\forest@temp@count>\forest@i\relax}% | |
\fi | |
\loop | |
\advance\forest@temp@count\forest@breakpath@step\relax | |
\expandafter\ifnum\forest@breakpath@test | |
\pgfpointintersectionoflines | |
{\pgfqpoint | |
{\csname\forest@bp@prefix\the\forest@temp@count x\endcsname}% | |
{\csname\forest@bp@prefix\the\forest@temp@count y\endcsname}% | |
}% | |
{\pgfpointadd | |
{\pgfqpoint | |
{\csname\forest@bp@prefix\the\forest@temp@count x\endcsname}% | |
{\csname\forest@bp@prefix\the\forest@temp@count y\endcsname}% | |
}% | |
{\pgfqpoint{\forest@xs}{\forest@ys}}% | |
}% | |
{\pgfqpoint{\forest@previous@x}{\forest@previous@y}}% | |
{\pgfqpoint{#1}{#2}}% | |
\pgfgetlastxy\forest@last@x\forest@last@y | |
\pgfsyssoftpath@lineto\forest@last@x\forest@last@y | |
\forest@append@point@to@inner@array | |
\forest@last@x\forest@last@y | |
{\forest@bp@prefix\the\forest@temp@count @}% | |
\csedef{\forest@bp@prefix(\the\pgf@x,\the\pgf@y)}{\the\forest@temp@count}% | |
\repeat | |
\fi | |
\forest@breakpath@op{#1}{#2}% | |
\def\forest@previous@x{#1}% | |
\def\forest@previous@y{#2}% | |
\let\forest@previous@i\forest@i | |
\let\forest@previous@px\forest@px | |
\let\forest@previous@py\forest@py | |
} | |
\def\forest@getnegativetightedgeofpath#1#2{% | |
\forest@get@onetightedgeofpath#1\forest@sort@ascending#2} | |
\def\forest@getpositivetightedgeofpath#1#2{% | |
\forest@get@onetightedgeofpath#1\forest@sort@descending#2} | |
\def\forest@get@onetightedgeofpath#1#2#3{% | |
{% | |
\forest@get@one@tightedgeofpath#1#2\forest@gep@edge | |
\global\let\forest@gep@global@edge\forest@gep@edge | |
}% | |
\let#3\forest@gep@global@edge | |
} | |
\def\forest@get@one@tightedgeofpath#1#2#3{% | |
\forest@projectpathtogrowline#1{forest@pp@}% | |
\forest@sortprojections{forest@pp@}% | |
\forest@processprojectioninfo{forest@pp@}{forest@pi@}% | |
\forest@breakpath#1{forest@pi@}\forest@brokenpath | |
\forest@sort@inner@arrays{forest@pi@}#2% | |
\forest@pathtodict\forest@brokenpath{forest@pi@}% | |
\forest@gettightedgeofpath@getedge | |
\pgfsyssoftpath@getcurrentpath\forest@edge | |
\forest@simplifypath\forest@edge#3% | |
} | |
\def\forest@getbothtightedgesofpath#1#2#3{% | |
{% | |
\forest@get@one@tightedgeofpath#1\forest@sort@ascending\forest@gep@firstedge | |
\c@pgf@counta=0 | |
\loop | |
\ifnum\c@pgf@counta<\forest@pi@n\relax | |
\forest@ppi@deflet{forest@pi@\the\c@pgf@counta @}% | |
\forest@reversearray\forest@ppi@let | |
{0}% | |
{\csname forest@pi@\the\c@pgf@counta @n\endcsname}% | |
\advance\c@pgf@counta 1 | |
\repeat | |
\forest@gettightedgeofpath@getedge | |
\pgfsyssoftpath@getcurrentpath\forest@edge | |
\forest@simplifypath\forest@edge\forest@gep@secondedge | |
\global\let\forest@gep@global@firstedge\forest@gep@firstedge | |
\global\let\forest@gep@global@secondedge\forest@gep@secondedge | |
}% | |
\let#2\forest@gep@global@firstedge | |
\let#3\forest@gep@global@secondedge | |
} | |
\def\forest@sort@inner@arrays#1#2{% | |
\c@pgf@counta=0 | |
\forest@loopa | |
\ifnum\c@pgf@counta<\csname#1n\endcsname | |
\c@pgf@countb=\csname#1\the\c@pgf@counta @n\endcsname\relax | |
\ifnum\c@pgf@countb>1 | |
\advance\c@pgf@countb -1 | |
\forest@ppi@deflet{#1\the\c@pgf@counta @}% | |
\forest@ppi@defcmp{#1\the\c@pgf@counta @}% | |
\forest@sort\forest@ppi@cmp\forest@ppi@let#2{0}{\the\c@pgf@countb}% | |
\fi | |
\advance\c@pgf@counta 1 | |
\forest@repeata | |
} | |
\def\forest@ppi@deflet#1{% | |
\edef\forest@ppi@let##1##2{% | |
\noexpand\csletcs{#1##1x}{#1##2x}% | |
\noexpand\csletcs{#1##1y}{#1##2y}% | |
\noexpand\csletcs{#1##1d}{#1##2d}% | |
}% | |
} | |
\def\forest@ppi@defcmp#1{% | |
\edef\forest@ppi@cmp##1##2{% | |
\noexpand\forest@sort@cmpdimcs{#1##1d}{#1##2d}% | |
}% | |
} | |
\let\forest@inpath\advance | |
\def\forest@pathtodict#1#2{% | |
\edef\forest@pathtodict@prefix{#2}% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@pathtodict@movetoop | |
\let\pgfsyssoftpath@linetotoken\forest@pathtodict@linetoop | |
\def\forest@pathtodict@subpathstart{}% | |
#1% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
} | |
\def\forest@pathtodict@movetoop#1#2{% | |
\def\forest@pathtodict@subpathstart{(#1,#2)-}% | |
} | |
\def\forest@pathtodict@linetoop#1#2{% | |
\if\relax\forest@pathtodict@subpathstart\relax\else | |
\let\forest@pathtodict@from\forest@pathtodict@subpathstart | |
\fi | |
\expandafter\let\csname\forest@pathtodict@prefix\forest@pathtodict@from-(#1,#2)\endcsname\forest@inpath | |
\def\forest@pathtodict@from{(#1,#2)-}% | |
\def\forest@pathtodict@subpathstart{}% | |
} | |
\def\forest@gettightedgeofpath@getedge{% | |
\pgfsyssoftpath@setcurrentpath\pgfutil@empty | |
\let\forest@last@x\relax | |
\let\forest@last@y\relax | |
\c@pgf@counta=0 | |
\forest@temp@count=\forest@pi@n\relax | |
\advance\forest@temp@count -1 | |
\edef\forest@nminusone{\the\forest@temp@count}% | |
\forest@loopa | |
\ifnum\c@pgf@counta<\forest@nminusone\relax | |
\forest@gettightedgeofpath@getedge@loopa | |
\forest@repeata | |
\ifnum\forest@nminusone<\forest@n\relax\else | |
\ifnum\csname forest@pi@\forest@nminusone @n\endcsname>0 | |
\forest@gettightedgeofpath@maybemoveto{\forest@nminusone}{0}% | |
\fi | |
\fi | |
} | |
\def\forest@gettightedgeofpath@getedge@loopa{% | |
\ifnum\csname forest@pi@\the\c@pgf@counta @n\endcsname>0 | |
\forest@gettightedgeofpath@maybemoveto{\the\c@pgf@counta}{0}% | |
\c@pgf@countb=0 | |
\forest@loopb | |
\ifnum\c@pgf@countb<\csname forest@pi@\the\c@pgf@counta @n\endcsname\relax | |
\forest@gettightedgeofpath@getedge@loopb | |
\forest@repeatb | |
\fi | |
\advance\c@pgf@counta 1 | |
} | |
\def\forest@gettightedgeofpath@getedge@loopb{% | |
\c@pgf@countc=0 | |
\advance\c@pgf@counta 1 | |
\edef\forest@aplusone{\the\c@pgf@counta}% | |
\advance\c@pgf@counta -1 | |
\forest@loopc | |
\ifnum\c@pgf@countc<\csname forest@pi@\forest@aplusone @n\endcsname\relax | |
\forest@tempfalse | |
\expandafter\ifx\csname forest@pi@(% | |
\csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb x\endcsname,% | |
\csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb y\endcsname)--(% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname,% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname)% | |
\endcsname\forest@inpath | |
\forest@temptrue | |
\else | |
\expandafter\ifx\csname forest@pi@(% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname,% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname)--(% | |
\csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb x\endcsname,% | |
\csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb y\endcsname)% | |
\endcsname\forest@inpath | |
\forest@temptrue | |
\fi | |
\fi | |
\ifforest@temp | |
\forest@gettightedgeofpath@maybemoveto{\the\c@pgf@counta}{\the\c@pgf@countb}% | |
\edef\forest@last@x{% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname}% | |
\edef\forest@last@y{% | |
\csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname}% | |
\pgfsyssoftpath@lineto\forest@last@x\forest@last@y | |
\c@pgf@countc=\csname forest@pi@\forest@aplusone @n\endcsname | |
\c@pgf@countb=\csname forest@pi@\the\c@pgf@counta @n\endcsname | |
\fi | |
\advance\c@pgf@countc 1 | |
\forest@repeatc | |
\advance\c@pgf@countb 1 | |
} | |
\def\forest@gettightedgeofpath@maybemoveto#1#2{% | |
\forest@temptrue | |
\ifx\forest@last@x\relax\else | |
\ifdim\forest@last@x=\csname forest@pi@#1@#2x\endcsname\relax | |
\ifdim\forest@last@y=\csname forest@pi@#1@#2y\endcsname\relax | |
\forest@tempfalse | |
\fi | |
\fi | |
\fi | |
\ifforest@temp | |
\edef\forest@last@x{\csname forest@pi@#1@#2x\endcsname}% | |
\edef\forest@last@y{\csname forest@pi@#1@#2y\endcsname}% | |
\pgfsyssoftpath@moveto\forest@last@x\forest@last@y | |
\fi | |
} | |
\def\forest@simplifypath#1#2{% | |
\pgfsyssoftpath@setcurrentpath\pgfutil@empty | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@simplifypath@moveto | |
\let\pgfsyssoftpath@linetotoken\forest@simplifypath@lineto | |
\let\forest@last@x\relax | |
\let\forest@last@y\relax | |
\let\forest@last@atan\relax | |
#1% | |
\ifx\forest@last@x\relax\else | |
\ifx\forest@last@atan\relax\else | |
\pgfsyssoftpath@lineto\forest@last@x\forest@last@y | |
\fi | |
\fi | |
\forest@restore@pgfsyssoftpath@tokendefs | |
\pgfsyssoftpath@getcurrentpath#2% | |
} | |
\def\forest@simplifypath@moveto#1#2{% | |
\ifx\forest@last@x\relax\else | |
\pgfsyssoftpath@lineto\forest@last@x\forest@last@y | |
\fi | |
\pgfsyssoftpath@moveto{#1}{#2}% | |
\def\forest@last@x{#1}% | |
\def\forest@last@y{#2}% | |
\let\forest@last@atan\relax | |
} | |
\def\forest@getedgeofpath@precision{1pt} | |
\def\forest@simplifypath@lineto#1#2{% | |
\ifx\forest@last@x\relax | |
\def\forest@last@x{#1}% | |
\def\forest@last@y{#2}% | |
\let\forest@last@atan\relax | |
\else | |
\pgfpointdiff{\pgfqpoint{#1}{#2}}{\pgfqpoint{\forest@last@x}{\forest@last@y}}% | |
\ifdim\pgf@x<\pgfintersectiontolerance | |
\ifdim-\pgf@x<\pgfintersectiontolerance | |
\pgf@x=0pt | |
\fi | |
\fi | |
\csname pgfmathatan2\endcsname{\pgf@x}{\pgf@y}% | |
\let\forest@current@atan\pgfmathresult | |
\ifx\forest@last@atan\relax | |
\def\forest@last@x{#1}% | |
\def\forest@last@y{#2}% | |
\let\forest@last@atan\forest@current@atan | |
\else | |
\pgfutil@tempdima=\forest@current@atan pt | |
\advance\pgfutil@tempdima -\forest@last@atan pt | |
\ifdim\pgfutil@tempdima<0pt\relax | |
\multiply\pgfutil@tempdima -1 | |
\fi | |
\ifdim\pgfutil@tempdima<\forest@getedgeofpath@precision\relax | |
\else | |
\pgfsyssoftpath@lineto\forest@last@x\forest@last@y | |
\let\forest@last@atan\forest@current@atan | |
\fi | |
\def\forest@last@x{#1}% | |
\def\forest@last@y{#2}% | |
\fi | |
\fi | |
} | |
\def\forest@getnegativerectangleedgeofpath#1#2{% | |
\forest@getnegativerectangleorbandedgeofpath{#1}{#2}{\the\pgf@xb}} | |
\def\forest@getpositiverectangleedgeofpath#1#2{% | |
\forest@getpositiverectangleorbandedgeofpath{#1}{#2}{\the\pgf@xb}} | |
\def\forest@getbothrectangleedgesofpath#1#2#3{% | |
\forest@getbothrectangleorbandedgesofpath{#1}{#2}{#3}{\the\pgf@xb}} | |
\def\forest@bandlength{5000pt} % something large (ca. 180cm), but still manageable for TeX without producing `too large' errors | |
\def\forest@getnegativebandedgeofpath#1#2{% | |
\forest@getnegativerectangleorbandedgeofpath{#1}{#2}{\forest@bandlength}} | |
\def\forest@getpositivebandedgeofpath#1#2{% | |
\forest@getpositiverectangleorbandedgeofpath{#1}{#2}{\forest@bandlength}} | |
\def\forest@getbothbandedgesofpath#1#2#3{% | |
\forest@getbothrectangleorbandedgesofpath{#1}{#2}{#3}{\forest@bandlength}} | |
\def\forest@getnegativerectangleorbandedgeofpath#1#2#3{% | |
\forest@path@getboundingrectangle@ls#1{\forest@grow}% | |
\edef\forest@gre@path{% | |
\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@ya}% | |
\noexpand\pgfsyssoftpath@linetotoken{#3}{\the\pgf@ya}% | |
}% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forest@grow}% | |
\forest@pgfpathtransformed\forest@gre@path | |
}% | |
\pgfsyssoftpath@getcurrentpath#2% | |
} | |
\def\forest@getpositiverectangleorbandedgeofpath#1#2#3{% | |
\forest@path@getboundingrectangle@ls#1{\forest@grow}% | |
\edef\forest@gre@path{% | |
\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@yb}% | |
\noexpand\pgfsyssoftpath@linetotoken{#3}{\the\pgf@yb}% | |
}% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forest@grow}% | |
\forest@pgfpathtransformed\forest@gre@path | |
}% | |
\pgfsyssoftpath@getcurrentpath#2% | |
} | |
\def\forest@getbothrectangleorbandedgesofpath#1#2#3#4{% | |
\forest@path@getboundingrectangle@ls#1{\forest@grow}% | |
\edef\forest@gre@negpath{% | |
\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@ya}% | |
\noexpand\pgfsyssoftpath@linetotoken{#4}{\the\pgf@ya}% | |
}% | |
\edef\forest@gre@pospath{% | |
\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@yb}% | |
\noexpand\pgfsyssoftpath@linetotoken{#4}{\the\pgf@yb}% | |
}% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forest@grow}% | |
\forest@pgfpathtransformed\forest@gre@negpath | |
}% | |
\pgfsyssoftpath@getcurrentpath#2% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forest@grow}% | |
\forest@pgfpathtransformed\forest@gre@pospath | |
}% | |
\pgfsyssoftpath@getcurrentpath#3% | |
} | |
\def\forest@distance@between@edge@paths#1#2#3{% | |
% #1, #2 = (edge) paths | |
% | |
% project paths | |
\forest@projectpathtogrowline#1{forest@p1@}% | |
\forest@projectpathtogrowline#2{forest@p2@}% | |
% merge projections (the lists are sorted already, because edge | |
% paths are |sorted|) | |
\forest@dbep@mergeprojections | |
{forest@p1@}{forest@p2@}% | |
{forest@P1@}{forest@P2@}% | |
% process projections | |
\forest@processprojectioninfo{forest@P1@}{forest@PI1@}% | |
\forest@processprojectioninfo{forest@P2@}{forest@PI2@}% | |
% break paths | |
\forest@breakpath#1{forest@PI1@}\forest@broken@one | |
\forest@breakpath#2{forest@PI2@}\forest@broken@two | |
% sort inner arrays ---optimize: it's enough to find max and min | |
\forest@sort@inner@arrays{forest@PI1@}\forest@sort@descending | |
\forest@sort@inner@arrays{forest@PI2@}\forest@sort@ascending | |
% compute the distance | |
\let\forest@distance\relax | |
\c@pgf@countc=0 | |
\loop | |
\ifnum\c@pgf@countc<\csname forest@PI1@n\endcsname\relax | |
\ifnum\csname forest@PI1@\the\c@pgf@countc @n\endcsname=0 \else | |
\ifnum\csname forest@PI2@\the\c@pgf@countc @n\endcsname=0 \else | |
\pgfutil@tempdima=\csname forest@PI2@\the\c@pgf@countc @0d\endcsname\relax | |
\advance\pgfutil@tempdima -\csname forest@PI1@\the\c@pgf@countc @0d\endcsname\relax | |
\ifx\forest@distance\relax | |
\edef\forest@distance{\the\pgfutil@tempdima}% | |
\else | |
\ifdim\pgfutil@tempdima<\forest@distance\relax | |
\edef\forest@distance{\the\pgfutil@tempdima}% | |
\fi | |
\fi | |
\fi | |
\fi | |
\advance\c@pgf@countc 1 | |
\repeat | |
\let#3\forest@distance | |
} | |
% merge projections: we need two projection arrays, both containing | |
% projection points from both paths, but each with the original | |
% points from only one path | |
\def\forest@dbep@mergeprojections#1#2#3#4{% | |
% TODO: optimize: v bistvu ni treba sortirat, ker je edge path že sortiran | |
\forest@sortprojections{#1}% | |
\forest@sortprojections{#2}% | |
\c@pgf@counta=0 | |
\c@pgf@countb=0 | |
\c@pgf@countc=0 | |
\edef\forest@input@prefix@one{#1}% | |
\edef\forest@input@prefix@two{#2}% | |
\edef\forest@output@prefix@one{#3}% | |
\edef\forest@output@prefix@two{#4}% | |
\forest@dbep@mp@iterate | |
\csedef{#3n}{\the\c@pgf@countc}% | |
\csedef{#4n}{\the\c@pgf@countc}% | |
} | |
\def\forest@dbep@mp@iterate{% | |
\let\forest@dbep@mp@next\forest@dbep@mp@iterate | |
\ifnum\c@pgf@counta<\csname\forest@input@prefix@one n\endcsname\relax | |
\ifnum\c@pgf@countb<\csname\forest@input@prefix@two n\endcsname\relax | |
\let\forest@dbep@mp@next\forest@dbep@mp@do | |
\else | |
\let\forest@dbep@mp@next\forest@dbep@mp@iteratefirst | |
\fi | |
\else | |
\ifnum\c@pgf@countb<\csname\forest@input@prefix@two n\endcsname\relax | |
\let\forest@dbep@mp@next\forest@dbep@mp@iteratesecond | |
\else | |
\let\forest@dbep@mp@next\relax | |
\fi | |
\fi | |
\forest@dbep@mp@next | |
} | |
\def\forest@dbep@mp@do{% | |
\forest@sort@cmptwodimcs% | |
{\forest@input@prefix@one\the\c@pgf@counta xp}% | |
{\forest@input@prefix@one\the\c@pgf@counta yp}% | |
{\forest@input@prefix@two\the\c@pgf@countb xp}% | |
{\forest@input@prefix@two\the\c@pgf@countb yp}% | |
\if\forest@sort@cmp@result=% | |
\forest@dbep@mp@@store@p\forest@input@prefix@one\c@pgf@counta | |
\forest@dbep@mp@@store@o\forest@input@prefix@one | |
\c@pgf@counta\forest@output@prefix@one | |
\forest@dbep@mp@@store@o\forest@input@prefix@two | |
\c@pgf@countb\forest@output@prefix@two | |
\advance\c@pgf@counta 1 | |
\advance\c@pgf@countb 1 | |
\else | |
\if\forest@sort@cmp@result>% | |
\forest@dbep@mp@@store@p\forest@input@prefix@two\c@pgf@countb | |
\forest@dbep@mp@@store@o\forest@input@prefix@two | |
\c@pgf@countb\forest@output@prefix@two | |
\advance\c@pgf@countb 1 | |
\else%< | |
\forest@dbep@mp@@store@p\forest@input@prefix@one\c@pgf@counta | |
\forest@dbep@mp@@store@o\forest@input@prefix@one | |
\c@pgf@counta\forest@output@prefix@one | |
\advance\c@pgf@counta 1 | |
\fi | |
\fi | |
\advance\c@pgf@countc 1 | |
\forest@dbep@mp@iterate | |
} | |
\def\forest@dbep@mp@@store@p#1#2{% | |
\csletcs | |
{\forest@output@prefix@one\the\c@pgf@countc xp}% | |
{#1\the#2xp}% | |
\csletcs | |
{\forest@output@prefix@one\the\c@pgf@countc yp}% | |
{#1\the#2yp}% | |
\csletcs | |
{\forest@output@prefix@two\the\c@pgf@countc xp}% | |
{#1\the#2xp}% | |
\csletcs | |
{\forest@output@prefix@two\the\c@pgf@countc yp}% | |
{#1\the#2yp}% | |
} | |
\def\forest@dbep@mp@@store@o#1#2#3{% | |
\csletcs{#3\the\c@pgf@countc xo}{#1\the#2xo}% | |
\csletcs{#3\the\c@pgf@countc yo}{#1\the#2yo}% | |
} | |
\def\forest@dbep@mp@iteratefirst{% | |
\forest@dbep@mp@iterateone\forest@input@prefix@one\c@pgf@counta\forest@output@prefix@one | |
} | |
\def\forest@dbep@mp@iteratesecond{% | |
\forest@dbep@mp@iterateone\forest@input@prefix@two\c@pgf@countb\forest@output@prefix@two | |
} | |
\def\forest@dbep@mp@iterateone#1#2#3{% | |
\loop | |
\ifnum#2<\csname#1n\endcsname\relax | |
\forest@dbep@mp@@store@p#1#2% | |
\forest@dbep@mp@@store@o#1#2#3% | |
\advance\c@pgf@countc 1 | |
\advance#21 | |
\repeat | |
} | |
\newif\ifforest@equaltotolerance | |
\def\forest@equaltotolerance#1#2{{% | |
\pgfpointdiff{#1}{#2}% | |
\ifdim\pgf@x<0pt \multiply\pgf@x -1 \fi | |
\ifdim\pgf@y<0pt \multiply\pgf@y -1 \fi | |
\global\forest@equaltotolerancefalse | |
\ifdim\pgf@x<\pgfintersectiontolerance\relax | |
\ifdim\pgf@y<\pgfintersectiontolerance\relax | |
\global\forest@equaltotolerancetrue | |
\fi | |
\fi | |
}} | |
\def\forest@save@pgfsyssoftpath@tokendefs{% | |
\let\forest@origmovetotoken\pgfsyssoftpath@movetotoken | |
\let\forest@origlinetotoken\pgfsyssoftpath@linetotoken | |
\let\forest@origcurvetosupportatoken\pgfsyssoftpath@curvetosupportatoken | |
\let\forest@origcurvetosupportbtoken\pgfsyssoftpath@curvetosupportbtoken | |
\let\forest@origcurvetotoken\pgfsyssoftpath@curvetototoken | |
\let\forest@origrectcornertoken\pgfsyssoftpath@rectcornertoken | |
\let\forest@origrectsizetoken\pgfsyssoftpath@rectsizetoken | |
\let\forest@origclosepathtoken\pgfsyssoftpath@closepathtoken | |
\let\pgfsyssoftpath@movetotoken\forest@badtoken | |
\let\pgfsyssoftpath@linetotoken\forest@badtoken | |
\let\pgfsyssoftpath@curvetosupportatoken\forest@badtoken | |
\let\pgfsyssoftpath@curvetosupportbtoken\forest@badtoken | |
\let\pgfsyssoftpath@curvetototoken\forest@badtoken | |
\let\pgfsyssoftpath@rectcornertoken\forest@badtoken | |
\let\pgfsyssoftpath@rectsizetoken\forest@badtoken | |
\let\pgfsyssoftpath@closepathtoken\forest@badtoken | |
} | |
\def\forest@badtoken{% | |
\PackageError{forest}{This token should not be in this path}{}% | |
} | |
\def\forest@restore@pgfsyssoftpath@tokendefs{% | |
\let\pgfsyssoftpath@movetotoken\forest@origmovetotoken | |
\let\pgfsyssoftpath@linetotoken\forest@origlinetotoken | |
\let\pgfsyssoftpath@curvetosupportatoken\forest@origcurvetosupportatoken | |
\let\pgfsyssoftpath@curvetosupportbtoken\forest@origcurvetosupportbtoken | |
\let\pgfsyssoftpath@curvetototoken\forest@origcurvetotoken | |
\let\pgfsyssoftpath@rectcornertoken\forest@origrectcornertoken | |
\let\pgfsyssoftpath@rectsizetoken\forest@origrectsizetoken | |
\let\pgfsyssoftpath@closepathtoken\forest@origclosepathtoken | |
} | |
\def\forest@extendpath#1#2#3{% | |
\pgf@process{#3}% | |
\pgfsyssoftpath@setcurrentpath#1% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@extendpath@moveto | |
\let\pgfsyssoftpath@linetotoken\forest@extendpath@lineto | |
#2% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
\pgfsyssoftpath@getcurrentpath#1% | |
} | |
\def\forest@extendpath@moveto#1#2{% | |
\forest@extendpath@do{#1}{#2}\pgfsyssoftpath@moveto | |
} | |
\def\forest@extendpath@lineto#1#2{% | |
\forest@extendpath@do{#1}{#2}\pgfsyssoftpath@lineto | |
} | |
\def\forest@extendpath@do#1#2#3{% | |
{% | |
\advance\pgf@x #1 | |
\advance\pgf@y #2 | |
#3{\the\pgf@x}{\the\pgf@y}% | |
}% | |
} | |
\def\forest@path@getboundingrectangle@ls#1#2{% | |
{% | |
\pgftransformreset | |
\pgftransformrotate{-(#2)}% | |
\forest@pgfpathtransformed#1% | |
}% | |
\pgfsyssoftpath@getcurrentpath\forest@gbr@rotatedpath | |
\forest@path@getboundingrectangle@xy\forest@gbr@rotatedpath | |
} | |
\def\forest@path@getboundingrectangle@xy#1{% | |
\forest@save@pgfsyssoftpath@tokendefs | |
\let\pgfsyssoftpath@movetotoken\forest@gbr@firstpoint | |
\let\pgfsyssoftpath@linetotoken\forest@gbr@firstpoint | |
#1% | |
\forest@restore@pgfsyssoftpath@tokendefs | |
} | |
\def\forest@gbr@firstpoint#1#2{% | |
\pgf@xa=#1 \pgf@xb=#1 \pgf@ya=#2 \pgf@yb=#2 | |
\let\pgfsyssoftpath@movetotoken\forest@gbr@point | |
\let\pgfsyssoftpath@linetotoken\forest@gbr@point | |
} | |
\def\forest@gbr@point#1#2{% | |
\ifdim#1<\pgf@xa\relax\pgf@xa=#1 \fi | |
\ifdim#1>\pgf@xb\relax\pgf@xb=#1 \fi | |
\ifdim#2<\pgf@ya\relax\pgf@ya=#2 \fi | |
\ifdim#2>\pgf@yb\relax\pgf@yb=#2 \fi | |
} | |
\newif\ifforesttikzcshack | |
\foresttikzcshacktrue | |
\newif\ifforest@install@keys@to@tikz@path@ | |
\forest@install@keys@to@tikz@path@true | |
\forestset{package@options/.cd, | |
external/.is if=forest@external@, | |
tikzcshack/.is if=foresttikzcshack, | |
tikzinstallkeys/.is if=forest@install@keys@to@tikz@path@, | |
} | |
\pgfkeys{/forest/external/.cd, | |
copy command/.initial={cp "\source" "\target"}, | |
optimize/.is if=forest@external@optimize@, | |
context/.initial={% | |
\forestOve{\csname forest@id@of@standard node\endcsname}{environment@formula}}, | |
depends on macro/.style={context/.append/.expanded={% | |
\expandafter\detokenize\expandafter{#1}}}, | |
} | |
\def\forest@external@copy#1#2{% | |
\pgfkeysgetvalue{/forest/external/copy command}\forest@copy@command | |
\ifx\forest@copy@command\pgfkeysnovalue\else | |
\IfFileExists{#1}{% | |
{% | |
\def\source{#1}% | |
\def\target{#2}% | |
\immediate\write18{\forest@copy@command}% | |
}% | |
}{}% | |
\fi | |
} | |
\newif\ifforest@external@ | |
\newif\ifforest@external@optimize@ | |
\forest@external@optimize@true | |
\ProcessPgfPackageOptions{/forest/package@options} | |
\ifforest@install@keys@to@tikz@path@ | |
\tikzset{fit to tree/.style={/forest/fit to tree}} | |
\fi | |
\ifforest@external@ | |
\ifdefined\tikzexternal@tikz@replacement\else | |
\usetikzlibrary{external}% | |
\fi | |
\pgfkeys{% | |
/tikz/external/failed ref warnings for={}, | |
/pgf/images/aux in dpth=false, | |
}% | |
\tikzifexternalizing{}{% | |
\forest@external@copy{\jobname.aux}{\jobname.aux.copy}% | |
}% | |
\AtBeginDocument{% | |
\tikzifexternalizing{% | |
\IfFileExists{\tikzexternalrealjob.aux.copy}{% | |
\makeatletter | |
\input \tikzexternalrealjob.aux.copy | |
\makeatother | |
}{}% | |
}{% | |
\newwrite\forest@auxout | |
\immediate\openout\forest@auxout=\tikzexternalrealjob.for.tmp | |
}% | |
\IfFileExists{\tikzexternalrealjob.for}{% | |
{% | |
\makehashother\makeatletter | |
\input \tikzexternalrealjob.for | |
}% | |
}{}% | |
}% | |
\AtEndDocument{% | |
\tikzifexternalizing{}{% | |
\immediate\closeout\forest@auxout | |
\forest@external@copy{\jobname.for.tmp}{\jobname.for}% | |
}% | |
}% | |
\fi | |
\newenvironment{forest}{\pgfkeysalso{/forest/begin forest}\Collect@Body\forest@env}{} | |
\long\def\Forest{\pgfkeysalso{/forest/begin forest}\@ifnextchar*{\forest@nogroup}{\forest@group}} | |
\def\forest@group#1{{\forest@env{#1}}} | |
\def\forest@nogroup*#1{\forest@env{#1}} | |
\newif\ifforest@externalize@tree@ | |
\newif\ifforest@was@tikzexternalwasenable | |
\long\def\forest@env#1{% | |
\let\forest@external@next\forest@begin | |
\forest@was@tikzexternalwasenablefalse | |
\ifdefined\tikzexternal@tikz@replacement | |
\ifx\tikz\tikzexternal@tikz@replacement | |
\forest@was@tikzexternalwasenabletrue | |
\tikzexternaldisable | |
\fi | |
\fi | |
\forest@externalize@tree@false | |
\ifforest@external@ | |
\ifforest@was@tikzexternalwasenable | |
\tikzifexternalizing{% | |
\let\forest@external@next\forest@begin@externalizing | |
}{% | |
\let\forest@external@next\forest@begin@externalize | |
}% | |
\fi | |
\fi | |
\forest@standardnode@calibrate | |
\forest@external@next{#1}% | |
} | |
\long\def\forest@begin@externalizing#1{% | |
\forest@external@setup{#1}% | |
\let\forest@external@next\forest@begin | |
\forest@externalize@inner@n=-1 | |
\ifforest@external@optimize@\forest@externalizing@maybeoptimize\fi | |
\forest@external@next{#1}% | |
\tikzexternalenable | |
} | |
\def\forest@externalizing@maybeoptimize{% | |
\edef\forest@temp{\tikzexternalrealjob-forest-\forest@externalize@outer@n}% | |
\edef\forest@marshal{% | |
\noexpand\pgfutil@in@ | |
{\expandafter\detokenize\expandafter{\forest@temp}.} | |
{\expandafter\detokenize\expandafter{\jobname}.}% | |
}\forest@marshal | |
\ifpgfutil@in@ | |
\else | |
\let\forest@external@next\@gobble | |
\fi | |
} | |
\long\def\forest@begin@externalize#1{% | |
\forest@external@setup{#1}% | |
\iftikzexternal@file@isuptodate | |
\setbox0=\hbox{% | |
\csname forest@externalcheck@\forest@externalize@outer@n\endcsname | |
}% | |
\fi | |
\iftikzexternal@file@isuptodate | |
\csname forest@externalload@\forest@externalize@outer@n\endcsname | |
\else | |
\forest@externalize@tree@true | |
\forest@externalize@inner@n=-1 | |
\forest@begin{#1}% | |
\ifcsdef{forest@externalize@@\forest@externalize@id}{}{% | |
\immediate\write\forest@auxout{% | |
\noexpand\forest@external | |
{\forest@externalize@outer@n}% | |
{\expandafter\detokenize\expandafter{\forest@externalize@id}}% | |
{\expandonce\forest@externalize@checkimages}% | |
{\expandonce\forest@externalize@loadimages}% | |
}% | |
}% | |
\fi | |
\tikzexternalenable | |
} | |
\def\forest@includeexternal@check#1{% | |
\tikzsetnextfilename{#1}% | |
\tikzexternal@externalizefig@systemcall@uptodatecheck | |
} | |
\def\makehashother{\catcode`\#=12}% | |
\long\def\forest@external@setup#1{% | |
% set up \forest@externalize@id and \forest@externalize@outer@n | |
% we need to deal with #s correctly (\write doubles them) | |
\setbox0=\hbox{\makehashother\makeatletter | |
\scantokens{\forest@temp@toks{#1}}\expandafter | |
}% | |
\expandafter\forest@temp@toks\expandafter{\the\forest@temp@toks}% | |
\edef\forest@temp{\pgfkeysvalueof{/forest/external/context}}% | |
\edef\forest@externalize@id{% | |
\expandafter\detokenize\expandafter{\forest@temp}% | |
@@% | |
\expandafter\detokenize\expandafter{\the\forest@temp@toks}% | |
}% | |
\letcs\forest@externalize@outer@n{forest@externalize@@\forest@externalize@id}% | |
\ifdefined\forest@externalize@outer@n | |
\global\tikzexternal@file@isuptodatetrue | |
\else | |
\global\advance\forest@externalize@max@outer@n 1 | |
\edef\forest@externalize@outer@n{\the\forest@externalize@max@outer@n}% | |
\global\tikzexternal@file@isuptodatefalse | |
\fi | |
\def\forest@externalize@loadimages{}% | |
\def\forest@externalize@checkimages{}% | |
} | |
\newcount\forest@externalize@max@outer@n | |
\global\forest@externalize@max@outer@n=0 | |
\newcount\forest@externalize@inner@n | |
\long\def\forest@external#1#2#3#4{% #1=n,#2=context+source code,#3=update check code, #4=load code | |
\ifnum\forest@externalize@max@outer@n<#1 | |
\global\forest@externalize@max@outer@n=#1 | |
\fi | |
\global\csdef{forest@externalize@@\detokenize{#2}}{#1}% | |
\global\csdef{forest@externalcheck@#1}{#3}% | |
\global\csdef{forest@externalload@#1}{#4}% | |
\tikzifexternalizing{}{% | |
\immediate\write\forest@auxout{% | |
\noexpand\forest@external{#1}% | |
{\expandafter\detokenize\expandafter{#2}}% | |
{\unexpanded{#3}}% | |
{\unexpanded{#4}}% | |
}% | |
}% | |
} | |
\def\forest@includeexternal#1{% | |
\edef\forest@temp{\pgfkeysvalueof{/forest/external/context}}% | |
\typeout{forest: Including external picture '#1' for forest context+code: | |
'\expandafter\detokenize\expandafter{\forest@externalize@id}'}% | |
{% | |
%\def\pgf@declaredraftimage##1##2{\def\pgf@image{\hbox{}}}% | |
\tikzsetnextfilename{#1}% | |
\tikzexternalenable | |
\tikz{}% | |
}% | |
} | |
\def\forest@includeexternal@box#1#2{% | |
\global\setbox#1=\hbox{\forest@includeexternal{#2}}% | |
} | |
\long\def\forest@begin#1{% | |
\iffalse{\fi\forest@parsebracket#1}% | |
} | |
\def\forest@parsebracket{% | |
\bracketParse{\forest@get@root@afterthought}\forest@root=% | |
} | |
\def\forest@get@root@afterthought{% | |
\expandafter\forest@get@root@afterthought@\expandafter{\iffalse}\fi | |
} | |
\long\def\forest@get@root@afterthought@#1{% | |
\ifblank{#1}{}{% | |
\forestOeappto{\forest@root}{given options}{,afterthought={\unexpanded{#1}}}% | |
}% | |
\forest@do | |
} | |
\def\forest@do{% | |
\forest@node@Compute@numeric@ts@info{\forest@root}% | |
\forestset{process keylist=given options}% | |
\forestset{stages}% | |
\pgfkeysalso{/forest/end forest}% | |
\ifforest@was@tikzexternalwasenable | |
\tikzexternalenable | |
\fi | |
} | |
\def\forest@standardnode@new{% | |
\advance\forest@node@maxid1 | |
\forest@fornode{\the\forest@node@maxid}{% | |
\forest@node@init | |
\forest@node@setname{standard node}% | |
}% | |
} | |
\def\forest@standardnode@calibrate{% | |
\forest@fornode{\forest@node@Nametoid{standard node}}{% | |
\edef\forest@environment{\forestove{environment@formula}}% | |
\forestoget{previous@environment}\forest@previous@environment | |
\ifx\forest@environment\forest@previous@environment\else | |
\forestolet{previous@environment}\forest@environment | |
\forest@node@typeset | |
\forestoget{calibration@procedure}\forest@temp | |
\expandafter\forestset\expandafter{\forest@temp}% | |
\fi | |
}% | |
} | |
\def\forestStandardNode[#1]#2#3#4{% | |
\let\forest@standardnode@restoretikzexternal\relax | |
\ifdefined\tikzexternaldisable | |
\ifx\tikz\tikzexternal@tikz@replacement | |
\tikzexternaldisable | |
\let\forest@standardnode@restoretikzexternal\tikzexternalenable | |
\fi | |
\fi | |
\forest@standardnode@new | |
\forest@fornode{\forest@node@Nametoid{standard node}}{% | |
\forestset{content=#1}% | |
\forestoset{environment@formula}{#2}% | |
\edef\forest@temp{\unexpanded{#3}}% | |
\forestolet{calibration@procedure}\forest@temp | |
\def\forest@calibration@initializing@code{}% | |
\pgfqkeys{/forest/initializing@code}{#4}% | |
\forestolet{initializing@code}\forest@calibration@initializing@code | |
\forest@standardnode@restoretikzexternal | |
} | |
} | |
\forestset{initializing@code/.unknown/.code={% | |
\eappto\forest@calibration@initializing@code{% | |
\noexpand\forestOget{\forest@node@Nametoid{standard node}}{\pgfkeyscurrentname}\noexpand\forest@temp | |
\noexpand\forestolet{\pgfkeyscurrentname}\noexpand\forest@temp | |
}% | |
} | |
} | |
\def\forest@initializefromstandardnode{% | |
\forestOve{\forest@node@Nametoid{standard node}}{initializing@code}% | |
} | |
\forestStandardNode[dj] | |
{% | |
\forestOve{\forest@node@Nametoid{standard node}}{content},% | |
\the\ht\strutbox,\the\pgflinewidth,% | |
\pgfkeysvalueof{/pgf/inner ysep},\pgfkeysvalueof{/pgf/outer ysep},% | |
\pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}% | |
} | |
{ | |
l sep={\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}}, | |
l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}}, | |
s sep={2*\pgfkeysvalueof{/pgf/inner xsep}} | |
} | |
{l sep,l,s sep} | |
\pgfqkeys{/forest/@cs}{% | |
name/.code={% | |
\edef\forest@cn{\forest@node@Nametoid{#1}}% | |
\forest@forestcs@resetxy}, | |
id/.code={% | |
\edef\forest@cn{#1}% | |
\forest@forestcs@resetxy}, | |
go/.code={% | |
\forest@go{#1}% | |
\forest@forestcs@resetxy}, | |
anchor/.code={\forest@forestcs@anchor{#1}}, | |
l/.code={% | |
\pgfmathsetlengthmacro\forest@forestcs@l{#1}% | |
\forest@forestcs@ls | |
}, | |
s/.code={% | |
\pgfmathsetlengthmacro\forest@forestcs@s{#1}% | |
\forest@forestcs@ls | |
}, | |
.unknown/.code={% | |
\expandafter\pgfutil@in@\expandafter.\expandafter{\pgfkeyscurrentname}% | |
\ifpgfutil@in@ | |
\expandafter\forest@forestcs@namegoanchor\pgfkeyscurrentname\forest@end | |
\else | |
\expandafter\forest@nameandgo\expandafter{\pgfkeyscurrentname}% | |
\forest@forestcs@resetxy | |
\fi | |
} | |
} | |
\def\forest@forestcs@resetxy{% | |
\ifnum\forest@cn=0 | |
\else | |
\global\pgf@x\forestove{x}% | |
\global\pgf@y\forestove{y}% | |
\fi | |
} | |
\def\forest@forestcs@ls{% | |
\ifdefined\forest@forestcs@l | |
\ifdefined\forest@forestcs@s | |
{% | |
\pgftransformreset | |
\pgftransformrotate{\forestove{grow}}% | |
\pgfpointtransformed{\pgfpoint{\forest@forestcs@l}{\forest@forestcs@s}}% | |
}% | |
\global\advance\pgf@x\forestove{x}% | |
\global\advance\pgf@y\forestove{y}% | |
\fi | |
\fi | |
} | |
\def\forest@forestcs@anchor#1{% | |
\edef\forest@marshal{% | |
\noexpand\forest@original@tikz@parse@node\relax | |
(\forestove{name}\ifx\relax#1\relax\else.\fi#1)% | |
}\forest@marshal | |
} | |
\def\forest@forestcs@namegoanchor#1.#2\forest@end{% | |
\forest@nameandgo{#1}% | |
\forest@forestcs@anchor{#2}% | |
} | |
\tikzdeclarecoordinatesystem{forest}{% | |
\forest@forthis{% | |
\forest@forestcs@resetxy | |
\ifdefined\forest@forestcs@l\undef\forest@forestcs@l\fi | |
\ifdefined\forest@forestcs@s\undef\forest@forestcs@s\fi | |
\pgfqkeys{/forest/@cs}{#1}% | |
}% | |
} | |
\endinput | |
%% | |
%% End of file `forest.sty'. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment