Current File : //usr/share/texlive/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex |
% Copyright 2018 by Renée Ahrens, Olof Frahm, Jens Kluttig, Matthias Schulz, Stephan Schuster
% Copyright 2018 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.
\ProvidesFileRCS{pgflibrarygraphdrawing.code.tex}
% check if luatex is running
\ifx\directlua\relax%
\pgferror{You need to run LuaTeX to use the graph drawing library}
\expandafter\endinput
\fi
\ifx\directlua\undefined%
\pgferror{You need to run LuaTeX to use the graph drawing library}
\expandafter\endinput
\fi
%
% All graph drawing keys normally live in the following namespace:
% /graph drawing.
%
\def\pgfgdset{\pgfqkeys{/graph drawing}}%
% Setup a key
%
% #1 = key
%
% Description:
%
% An internal macro that sets up #1 as a graph drawing key.
\def\pgfgd@callbackkey#1{%
\pgf@gd@setup@forwards{#1}%
\pgfutil@g@addto@macro\pgf@gd@forwards@list{\pgf@gd@setup@forwards{#1}}%
}%
\def\pgf@gd@setup@forwards#1{%
\let\pgf@temp\pgfutil@empty
\foreach \pgf@gd@path in \pgf@gd@forwarding@list {%
\ifx\pgf@gd@path\pgfutil@empty\else%
\expandafter\pgfutil@g@addto@macro%
\expandafter\pgf@temp\expandafter{%
\expandafter\pgfkeys\expandafter{\pgf@gd@path#1/.forward to=/graph drawing/#1}}%
\fi%
}%
\pgf@temp
}%
\let\pgf@gd@forwards@list\pgfutil@empty
% Append to the forwarding list:
%
% #1 = paths to append to the forwarding list
%
% Description:
%
% Append the paths in #1 (with trailing slashes) to the forwarding
% list.
%
% If algorithms have already been declared, forwarding will also be
% setup for them (using a bit of magic...).
\def\pgfgdappendtoforwardinglist#1{%
\let\pgf@gd@forwarding@list@orig\pgf@gd@forwarding@list
\def\pgf@gd@forwarding@list{#1}%
\pgf@gd@forwards@list%
\expandafter\def\expandafter\pgf@gd@forwarding@list\expandafter{\pgf@gd@forwarding@list@orig,#1}%
}%
\let\pgf@gd@forwarding@list\pgfutil@empty
%
%
% Callbacks
%
% The following macros are called *from* the binding layer. You do not
% call them from the pgf layer.
%
%
% Callback for declaring a graph parameter key
%
% #1 = Parameter key
% #2 = Parameter type
%
% Description:
%
% When a graph drawing algorithm starts working, a set of options,
% called "graph drawing parameters" in the following, can influence the
% way the algorithm works. For instance, an graph drawing parameter
% might be the average distance between vertices which the algorithm
% should take into account. Another example might be the fact the
% certain nodes are special nodes and that a certain edge should have
% a large label.
%
% These graph drawing parameters are different from "usual" pgf
% options: An algorithmic parameter influenced the way the algorithm
% works, while usual options normally only influence how the result
% looks like. For instance, the fact that a node is red is not an
% graph drawing parameter (usually, at least), while the shape of a node
% might be an graph drawing parameter.
%
% Graph drawing parameters are declared by the algorithmic layer
% (since only this layer "knows" which parameters there are). The
% binding to TeX will call the \pgfgddeclareparameter function
% internally.
%
% Specifying the set of graph drawing parameters for a given graph or
% node or edge works as follows: When the graph drawing engine is
% started for a graph (using \pgfgdbeginscope), a snapshot is taken of
% all graph drawing parameters currently setup at this
% point. Similarly, when a node is created inside such a scope, a
% snapshot is taken of the set of all graph drawing parameters in
% force at this point is taken and stored together with the
% node. Finally, when an edge is created, a snapshot of the setting of
% the graph drawing parameters is taken.
\def\pgfgdcallbackdeclareparameter#1#2{%
\pgfkeysdef{/graph drawing/#1}{\pgf@gd@handle@parameter{#1}{#2}{##1}}%
\pgfgd@callbackkey{#1}%
}%
\def\pgf@gd@handle@parameter#1#2#3{%
\def\pgf@temp{#3}%
\ifx\pgf@temp\pgfkeysnovalue@text%
\let\pgfgdresult\pgfgd@niltext%
\else%
\pgfkeys{/graph drawing/conversions/#2={#3}}%
\fi%
\advance\pgf@gd@parameter@stack@height by1\relax%
\pgf@gd@parameter@stack@height\directlua{%
local new, main = pgf.gd.interface.InterfaceToDisplay.pushOption('\pgfutil@luaescapestring{#1}',\pgfgdresult,\the\pgf@gd@parameter@stack@height)
tex.print(new..'\pgfutil@luaescapestring{\relax}')
if main then
tex.print('\pgfutil@luaescapestring{\noexpand\pgfgdtriggerrequest}')
end}%
}%
\newcount\pgf@gd@parameter@stack@height
\def\pgfgdtriggerrequest{\pgfgdset{@request scope and layout}}%
% Conversions are used to adapt the syntactic description of a
% parameter on the TikZ layer to the one expected by Lua. The set of
% permissible conversions is described in
% InterfaceToAlgorithms.declareParameter.
\pgfgdset{
conversions/string/.code=\def\pgfgdresult{'\pgfutil@luaescapestring{\detokenize{#1}}'},
conversions/raw/.code=\def\pgfgdresult{#1},
conversions/nil/.code=\let\pgfgdresult\pgfgd@niltext,
conversions/boolean/.code=\def\pgf@test{#1}\ifx\pgf@test\pgf@truetext\def\pgfgdresult{true}\else\ifx\pgf@test\pgfkeysnovalue@text\def\pgfgdresult{true}\else\def\pgfgdresult{false}\fi\fi,
conversions/number/.code=\pgfmathparse{#1}\let\pgfgdresult\pgfmathresult,
conversions/length/.code=\pgfmathparse{#1}\let\pgfgdresult\pgfmathresult,
conversions/time/.code=\pgfparsetime{#1}\let\pgfgdresult\pgftimeresult,
conversions/direction/.code=\pgf@lib@gd@grow@dir{#1}\let\pgfgdresult\pgfmathresult,
conversions/canvas coordinate/.code args={(#1pt,#2pt)}{\edef\pgfgdresult{pgf.gd.model.Coordinate.new(#1,#2)}},
% deprecated, will be removed:
conversions/coordinate/.code args={(#1pt,#2pt)}{\edef\pgfgdresult{{#1,#2}}}
}%
\def\pgf@truetext{true}%
\def\pgfgd@niltext{nil}%
\def\pgf@lib@gd@grow@dir#1{%
\def\pgf@temp{#1}%
\ifx\pgf@temp\pgf@gd@lib@active@bar%
\def\pgfmathresult{-90}
\else%
\ifcsname pgf@orient@direction@#1\endcsname%
\expandafter\let\expandafter\pgfmathresult\csname pgf@orient@direction@#1\endcsname%
\else
\pgfmathparse{#1}%
\fi
\fi
}%
\def\pgf@orient@direction@down{-90}%
\def\pgf@orient@direction@up{90}%
\def\pgf@orient@direction@left{180}%
\def\pgf@orient@direction@right{0}%
\def\pgf@orient@direction@south{-90}%
\def\pgf@orient@direction@north{90}%
\def\pgf@orient@direction@west{180}%
\def\pgf@orient@direction@east{0}%
\expandafter\def\csname pgf@orient@direction@north east\endcsname{45}%
\expandafter\def\csname pgf@orient@direction@north west\endcsname{135}%
\expandafter\def\csname pgf@orient@direction@south east\endcsname{-45}%
\expandafter\def\csname pgf@orient@direction@south west\endcsname{-135}%
\expandafter\def\csname pgf@orient@direction@-\endcsname{0}%
\expandafter\def\csname pgf@orient@direction@|\endcsname{-90}%
{%
\catcode`\|=13
\gdef\pgf@gd@lib@active@bar{|}%
}%
% Callback for starting the rendering of a collection kind
%
% #1 = Kind
% #2 = Layer
%
% Description:
%
% Executes /graph drawing/#1/begin rendering/.try
%
\def\pgfgdcallbackrendercollectionkindstart#1#2{%
\ifnum#2<0\relax
\setbox\pgf@gd@prekind@box=\hbox\bgroup%
\unhbox\pgf@gd@prekind@box%
\else%
\setbox\pgf@gd@postkind@box=\hbox\bgroup%
\unhbox\pgf@gd@postkind@box%
\fi%
\pgfgdset{/graph drawing/#1/begin rendering/.try}%
}%
% Callback for ending the rendering of a collection kind
%
% #1 = Kind
% #2 = Layer
%
% Description:
%
% Executes /graph drawing/#1/end rendering/.try
%
\def\pgfgdcallbackrendercollectionkindstop#1#2{%
\pgfgdset{/graph drawing/#1/end rendering/.try}%
\egroup % close box
}%
% Callback for rendering a collection
%
% #1 = Kind
% #2 = Options
%
% Description:
%
% Executes /graph drawing/#1/render/.try={#2}
%
\def\pgfgdcallbackrendercollection#1#2{
\pgfgdset{/graph drawing/#1/render/.try={#2}}
}%
% Graph events
%
% Although a graph consists of nodes and edges, during the
% construction of the graph a lot of information concerning the
% structure of the graph is often available. For instance, as we
% specify a graph using the child-syntax, we do not only which edges
% are present, but we can implicitly specify an ordering on the
% nodes. Even more, there is even information available concerning
% nodes that are not present at all: A child[missing] is not present
% as a node or an edge, but a tree drawing algorithm will want to know
% about this child nevertheless.
%
% In order to communicate such information to the graph drawing
% engine, "events" are used. As a graph is created, in addition to
% nodes and edges, "events" may happen. The events come in a
% sequential order and they are stored together with the graph. For
% each node and each edge, its index in the event sequence is
% stored, that is, it is stored how many events happened before the
% node or edge was created.
%
% Internally, an event consists of a name and, possibly, some
% parameters. When the parameter is created on the tikz level, it will
% be a string that is passed down to Lua. Internally created events
% will also have parameters that are objects.
%
% Two events are a bit special since they get special internal
% support: The begin and end events. The first signals that some kind
% of group has started; which is closed by the corresponding end
% event. The "kind" of group is indicated by the parameter of the
% begin event.
%
%
%
% Standard events are:
%
% For each node entered into a graph, a "node" event is automatically
% created internally with the parameter being the node. However, you
% can also create this event yourself. In this case, the parameter
% will be a string and will mean that the node is "virtual" or
% "missing", but space should be reserved for it, if possible (this is
% use, for instance, by certain tree layouts).
%
% For each edge entered into a graph, an "edge" event is automatically
% created, with the edge as the parameter. Again, an event with a
% string parameter corresponds to a "non-existing" node.
%
%
% Standard event groups are:
%
%
% The "descendants" event group include a set of nodes that, at least
% inside the specification, are descendants of the last node
%
% begin descendants
% ...
% end
%
%
% The "array" event group collects together some nodes in an array of
% nodes. This can be used, for instance, to specify matrices.
%
% begin array
% ...
% end
% Create a new event
%
% #1 = event name (should be a valid lua identifier name)
% #2 = parameter (some text)
%
% Description:
%
% Adds a new event to the event sequence of the graph
\def\pgfgdevent#1#2{%
\directlua{pgf.gd.interface.InterfaceToDisplay.createEvent('\pgfutil@luaescapestring{#1}', '\pgfutil@luaescapestring{#2}')}%
}%
% Start an event group
%
% #1 = kind of event group
%
% Description:
%
% Creates a begin event with #1 as the parameter of the begin
% event.
\def\pgfgdbegineventgroup#1{%
\pgfgdevent{begin}{#1}%
}%
% End an event group
%
% Description:
%
% Creates an end event.
\def\pgfgdendeventgroup{%
\pgfgdevent{end}{}%
}%
% Creates an event group for the current TeX group
%
% #1 = event group name
%
% Description:
%
% Issues a begin event for #1 and, using \aftergroup, adds an end
% event at the end of the current tex group.
\def\pgfgdeventgroup#1{%
\pgfgdbegineventgroup{#1}%
\aftergroup\pgfgdendeventgroup%
}%
%
% Nodes
%
%
% Callback method for \pgfpositionnodelater
%
% This function is called by \pgfnode whenever a node has been newly
% created inside a graph drawing scope. It will create a new vertex on
% the Lua layer.
%
\def\pgf@gd@positionnode@callback{%
{%
% evaluate coordinates
\pgfmathsetmacro{\pgf@gd@node@minx}{\pgfpositionnodelaterminx}%
\pgfmathsetmacro{\pgf@gd@node@miny}{\pgfpositionnodelaterminy}%
\pgfmathsetmacro{\pgf@gd@node@maxx}{\pgfpositionnodelatermaxx}%
\pgfmathsetmacro{\pgf@gd@node@maxy}{\pgfpositionnodelatermaxy}%
% Assemble the Path object:
\directlua{pgf.temp = require 'pgf.gd.model.Path'.new ()}%
\let\pgfsyssoftpath@movetotoken\pgf@gd@movetotoken%
\let\pgfsyssoftpath@linetotoken\pgf@gd@linetotoken%
\let\pgfsyssoftpath@rectcornertoken\pgf@gd@rectcornertoken%
\let\pgfsyssoftpath@curvetosupportatoken\pgf@gd@curvetosupportatoken%
\let\pgfsyssoftpath@closepathtoken\pgf@gd@closepathtoken%
\pgfpositionnodelaterpath%
%
\pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
%
{%
\pgf@process{\pgfpointanchor{\pgfpositionnodelatername}{center}}
\pgfsettransform{\csname pgf@sh@nt@\pgfpositionnodelatername\endcsname}%
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
% call lua system library to create a lua node object
\directlua{
pgf.gd.interface.InterfaceToDisplay.createVertex(
string.sub('\pgfutil@luaescapestring{\pgfpositionnodelatername}',30), % strip "not yet positionedPGFINTERNAL"
'\pgfutil@luaescapestring{\csname pgf@sh@ns@\pgfpositionnodelatername\endcsname}',
pgf.temp:pad((\pgf@sys@tonumber\pgf@xa+\pgf@sys@tonumber\pgf@ya)/2), % Padded path
\the\pgf@gd@parameter@stack@height, % Stack height
{% Binding info
x_min = \pgf@gd@node@minx,
y_min = \pgf@gd@node@miny,
x_max = \pgf@gd@node@maxx,
y_max = \pgf@gd@node@maxy,
tex_box_number = \pgfpositionnodelaterbox
},
{% Anchors
center = require 'pgf.gd.model.Coordinate'.new(\pgf@sys@tonumber\pgf@x,\pgf@sys@tonumber\pgf@y)
}
)
pgf.temp = nil
}
}%
}%
\def\pgf@gd@movetotoken#1#2{\directlua{pgf.temp:appendMoveto(\Pgf@geT#1,\Pgf@geT#2)}}%
\def\pgf@gd@linetotoken#1#2{\directlua{pgf.temp:appendLineto(\Pgf@geT#1,\Pgf@geT#2)}}%
\def\pgf@gd@rectcornertoken#1#2#3#4#5{%
\directlua{%
local x,y,dx,dy=\Pgf@geT#1,\Pgf@geT#2,\Pgf@geT#4,\Pgf@geT#5
pgf.temp:appendMoveto(x,y)
pgf.temp:appendLineto(x,y+dy)
pgf.temp:appendLineto(x+dx,y+dy)
pgf.temp:appendLineto(x+dx,y)
pgf.temp:appendClosepath()%
}%
}%
\def\pgf@gd@curvetosupportatoken#1#2#3#4#5#6#7#8{\directlua{pgf.temp:appendCurveto(\Pgf@geT#1,\Pgf@geT#2,\Pgf@geT#4,\Pgf@geT#5,\Pgf@geT#7,\Pgf@geT#8)}}%
\def\pgf@gd@closepathtoken#1#2{\directlua{pgf.temp:appendClosepath()}}%
% Set options for an already existing node
%
% #1 = node name
%
% These node parameters of #1 will be updated with the current values
% of the node parameters. The node #1 must previously have been passed
% to the gd engine. If some of the options have already been set for
% the node, these settings will be overruled.
\def\pgfgdsetlatenodeoption#1{%
\directlua{
pgf.gd.interface.InterfaceToDisplay.addToVertexOptions('\pgfutil@luaescapestring{#1}',\the\pgf@gd@parameter@stack@height)
}
}%
%
% A callback for rendering (finally positioning) a node
%
% #1 = name of the node
% #2 = x min of the bounding box
% #3 = x max of the bounding box
% #4 = y min of the bounding box
% #5 = y max of the bounding box
% #6 = desired x pos of the node
% #7 = desired y pos of the node
% #8 = box register number of the TeX node
% #9 = animation code
%
% This callback will be called by the engine for every original node
% when it finally needs to placed at a final position.
\def\pgfgdcallbackrendernode#1#2#3#4#5#6#7#8#9{%
{%
\def\pgfpositionnodelatername{#1}
\def\pgfpositionnodelaterminx{#2}
\def\pgfpositionnodelatermaxx{#3}
\def\pgfpositionnodelaterminy{#4}
\def\pgfpositionnodelatermaxy{#5}
\directlua{pgf.gd.interface.InterfaceCore.binding:retrieveBox(#8,\pgfpositionnodelaterbox)}
\def\pgf@temp{#9}%
\ifx\pgf@temp\pgfutil@empty%
\pgfpositionnodenow{\pgfqpoint{#6}{#7}}%
\else%
\pgfset{every graphdrawing animation/.try}%
\pgfset{every graphdrawing node animation/.try}%
#9%
\pgfuseid{pgf@gd}%
\pgfidscope%
\pgfpositionnodenow{\pgfqpoint{#6}{#7}}%
\endpgfidscope%
\fi%
}%
}%
\ifx\pgfanimateattribute\pgfutil@undefined
\def\pgfanimateattribute#1#2{\tikzerror{You need to say \string\usetikzlibrary{animations} for animated graphs}}%
\fi
% Adds an edge to the graph
%
% #1 = first node
% #2 = second node
% #3 = edge direction
% #4 = edge options (will be executed in a protected environment)
% #5 = aux stuff (curtesy for TikZ -- edge nodes)
%
% Description:
%
% Creating an edge means that you tell the graph drawing algorithm
% that #1 and #2 are connected. The "kind" of connection is indicated
% by #3, which may be one of the following:
%
% -> = a directed edge (also known as an arc) from #1 to #2
% -- = an undirected edge between #1 and #2
% <- = a directed edge from #2 to #1, but with the "additional hint"
% that this is a "backward" edge. A graph drawing algorithm may
% or may not take this hint into account
% <-> = a bi-directed edge between #1 and #2.
%
%
% The parameters #4 and #5 are a bit more tricky. When an edge between
% two vertices of a graph is created via \pgfgdedge, nothing is
% actually done immediately. After all, without knowing the final
% positions of the nodes #1 and #2, there is no way of
% creating the actual drawing commands for the edge. Thus, the actual
% drawing of the edge is done only when the graph drawing algorithm is
% done (namely in the macro \pgfgdcallbackedge, see later).
%
% Because of this "delayed" drawing of edges, options that influence
% the edge must be retained until the moment when the edge is actually
% drawn. Parameters #4 and #5 store such options.
%
% Let us start with #4. This parameter should be set to a list of
% key-value pairs like
%
% /tikz/.cd, color=red, very thick, this edge must be vertical
%
% Some of these options may be of interest to the graph drawing
% algorithm (like the last option) while others will
% only be important during the drawing of edge (like the first
% option). The options that are important for the graph drawing
% algorithm must be passed to the algorithm via setting keys that have
% been declared using the handler .edge parameter (see
% above).
%
% The tricky part is that options that are of interest to the graph
% drawing algorithm must be executed *before* the algorithm starts,
% but the options as a whole are usually only executed during the
% drawing of the edges, which is *after* the algorithm has finished.
%
% To overcome this problem, the following happens:
%
% The options in #4 are executed "tentatively" inside
% \pgfgdedge. However, this execution is done in a "heavily guarded
% sandbox" where all effects of the options (like changing the
% color or the line width) do not propagate beyond the sandbox. Only
% the changes of the graph drawing edge parameters leave the
% sandbox. These parameters are then passed down to the graph drawing
% engine.
%
% Later, when the edge is drawn using \pgfgdcallbackedge, the options #4
% are available once more and then they are executed normally.
%
% Note that when the options in #4 are executed, no path is
% preset. Thus, you typically need to start it with, say, /tikz/.cd.
%
%
% The text in #5 is some "auxiliary" text that is simply stored away
% and later directly to \pgfgdcallbackedge. This is a curtesy to TikZ,
% which can use it to store its node labels.
%
% Example:
%
% \pgfgdedge{A}{B}{->}{red}{}
%
\def\pgfgdedge#1#2#3#4#5{%
% Ok, setup sandbox
\begingroup%
\setbox0=\hbox{{%
\pgfinterruptpath%
\pgfgdprepareedge%
\pgfkeys{#4}%
% create edge in Lua
\toks0={#4}%
\toks1={#5}%
\directlua{
pgf.gd.interface.InterfaceToDisplay.createEdge(
'\pgfutil@luaescapestring{#1}','\pgfutil@luaescapestring{#2}','\pgfutil@luaescapestring{#3}',
\the\pgf@gd@parameter@stack@height,
{ pgf_options = '\pgfutil@luaescapestring{\the\toks0}',
pgf_edge_nodes = '\pgfutil@luaescapestring{\the\toks1}',
})
}%
\endpgfinterruptpath%
}}%
\endgroup%
}%
\let\pgfgdprepareedge=\pgfutil@empty
\def\pgfgdaddprepareedgehook#1{\expandafter\def\expandafter\pgfgdprepareedge\expandafter{\pgfgdprepareedge#1}}%
\newif\ifpgf@gd@nodes@behind@edges
% Define a callback for rendering edges
%
% #1 = macro name
%
% Descriptions:
%
% This is a callback from the graph drawing engine. At the end of the
% creation of a graph, when the nodes have been positioned, this macro
% is called once for each edge. The macro should take the following
% parameters:
%
% #1 = from node, optionally followed by "." and the tail anchor
% #2 = to node, optionally followed by "." and the head anchor
% #3 = direction (<-, --, ->, or <->)
% #4 = original options
% #5 = aux text (typically edge nodes)
% #6 = algorithm-generated options
% #7 = bend information
% #8 = animations
%
% The first five parameters are the original values that were passed
% down to the \pgfgdedge command.
%
% #6 contains options that have been "computed by the algorithm". For
% instance, an algorithm might have determined, say, flow capacities
% for edges and it might now wish to communicate this information back
% to the upper layers. These options should be executed with the path
% /graph drawing.
%
% #7 contains algorithmically-computed information concerning how the
% edge should bend. This will be a text like
% "--(10pt,20pt)--(30pt,40pt)" in tikz-syntax, using the path
% operations "--", "..controls" and "--cycle".
%
% By default, a simple line is drawn between the nodes. Usually, you
% will wish to install a more "fancy" callback, here.
\def\pgfgdsetedgecallback#1{\let\pgfgdcallbackedge=#1}%
\def\pgfgddefaultedgecallback#1#2#3#4#5#6#7#8{%
{%
\def\pgf@temp{#8}%
\ifx\pgf@temp\pgfutil@empty%
\else%
\pgfset{every graphdrawing animation/.try}%
\pgfset{every graphdrawing edge animation/.try}%
#8%
\pgfuseid{pgf@gd}%
\pgfidscope%
\fi%
\pgfscope
\pgfpathmoveto{
\pgfutil@in@.{#1}%
\ifpgfutil@in@
\pgf@gd@unravel#1\relax%
\else
\pgfpointshapeborder{#1}{\pgfpointanchor{#2}{center}}
\fi
}
\pgfpathlineto{
\pgfutil@in@.{#2}%
\ifpgfutil@in@
\pgf@gd@unravel#2\relax%
\else
\pgfpointshapeborder{#2}{\pgfpointanchor{#1}{center}}
\fi
}
\pgfusepath{stroke}
\endpgfscope
\ifx\pgf@temp\pgfutil@empty%
\else%
\endpgfidscope%
\fi%
}
}%
\pgfgdsetedgecallback{\pgfgddefaultedgecallback}%
\def\pgf@gd@unravel#1.#2\relax{%
\pgfpointanchor{#1}{#2}%
}%
% Callbacks: Called before the shipout of nodes and edges starts
%
% First, the general begin shipout is called. Then, the node shipout
% starts, the nodes are created, and then the end of the node shipout
% is signaled. Next, the edge shipout starts and ends. Finally, the
% end shipout is called.
\def\pgfgdcallbackbeginshipout{%
\pgfscope%
\catcode`\@=11\relax%
\setbox\pgf@gd@prekind@box=\box\pgfutil@voidb@x%
\setbox\pgf@gd@postkind@box=\box\pgfutil@voidb@x%
}%
\def\pgfgdcallbackendshipout{%
\box\pgf@gd@prekind@box%
\ifpgf@gd@nodes@behind@edges%
\box\pgf@gd@node@box%
\box\pgf@gd@edge@box%
\else%
\box\pgf@gd@edge@box%
\box\pgf@gd@node@box%
\fi%
\box\pgf@gd@postkind@box%
\endpgfscope
}%
\newbox\pgf@gd@node@box
\newbox\pgf@gd@edge@box
\newbox\pgf@gd@prekind@box
\newbox\pgf@gd@postkind@box
\def\pgfgdcallbackbeginnodeshipout{%
\setbox\pgf@gd@node@box=\hbox\bgroup%
}%
\def\pgfgdcallbackendnodeshipout{%
\egroup%
}%
\def\pgfgdcallbackbeginedgeshipout{%
\setbox\pgf@gd@edge@box=\hbox\bgroup%
}%
\def\pgfgdcallbackendedgeshipout{%
\egroup
}%
% Generate a node
%
% This callback is called from the engine whenever an algorithm
% generates a new node internally.
%
% #1 = name of the node
% #2 = shape of the node
% #3 = options generated by the algorithm in key-value syntax. The set
% of generated options is algorithm-dependent.
% #4 = text
%
% This is an internal function and will be called by the binding layer
\def\pgfgdcallbackcreatevertex#1#2#3#4{%
{
\pgfkeys{#3}
\pgfnode{#2}{\pgfkeysvalueof{/graph drawing/generated
node/anchor}}{#4}{#1}{\pgfkeysvalueof{/graph drawing/generated
node/use path}}
}
}%
\pgfkeys{
/graph drawing/generated node/anchor/.initial=center,
/graph drawing/generated node/use path/.initial=\pgfusepath{}
}%
%
% Sublayouts
%
% Description: For a general introduction to (sub)layouts, see
% Section~\ref{section-gd-sublayouts} in the manual.
%
\def\pgfgdbeginlayout{
\begingroup
\pgfgdlayoutscopeactivetrue
\advance\pgf@gd@parameter@stack@height by1\relax%
\directlua{pgf.gd.interface.InterfaceToDisplay.pushLayout(\the\pgf@gd@parameter@stack@height)}
}%
\def\pgfgdendlayout{
\endgroup%
}%
% Creates a subgraph node
%
% #1 = name
% #2 = node options
% #3 = node text
%
% Description:
%
% A subgraph node is a node that "surrounds" the nodes of a
% subgraph. The special property of a subgraph node opposed to a
% normal node is that it is created only after the subgraph has been
% laid out. However, the difference to a collection like "hyper" is
% that the node is available immediately as a normal node in the sense
% that you can connect edges to it.
%
% What happens internally is that subgraph nodes get "registered"
% immediately both on the pgf level and on the lua level, but the
% actual node is only created inside the layout pipeline using a
% callback. The actual node creation happens when the innermost layout
% in which the subgraph node is declared has finished.
%
% When you create a subgraph node using this macro, you also start a
% collection (of an internal kind) that stores the subgraph. All
% following nodes in the current TeX scope will become part of this
% collection.
%
% See |InterfaceToDisplay.pushSubgraphVertex| for details.
\def\pgfgdsubgraphnode#1#2#3{%
\advance\pgf@gd@parameter@stack@height by1\relax%
{%
% create edge in Lua
\toks0={#2}%
\toks1={#3}%
\directlua{pgf.gd.interface.InterfaceToDisplay.pushSubgraphVertex%
('\pgfutil@luaescapestring{#1}',\the\pgf@gd@parameter@stack@height,
{
shape = 'rectangle', % typically overwritten by the pgf_options:
pgf_options = '\pgfutil@luaescapestring{\the\toks0}',
text = '\pgfutil@luaescapestring{\the\toks1}',
})
}%
}
}%
\def\pgfgdsubgraphnodecontents#1{% helper function
\hbox to \pgfkeysvalueof{/graph drawing/subgraph bounding box width}{%
\vrule width0pt height\pgfkeysvalueof{/graph drawing/subgraph bounding box height}\hfil}%
}%
\pgfgdset{
subgraph point cloud/.initial=,
subgraph bounding box width/.initial=,
subgraph bounding box height/.initial=,
}%
%
% Requests
%
% Description:
%
% This key is used to ``request'' a graph drawing scope and a
% layout. The objective of this key is to make it easier for users and
% algorithm designers to control the slightly involved
% back-and-forth-calling between the different layers.
%
% This key does the following: When called inside a pgfpicture
% (otherwise, the call is "illegal"), it will call a call-back with
% two parameters. This callback will get passed some code that should
% be executed at the beginning of ``the next scope'' and some code
% that should be executed at the end of that scope.
%
% The code passed to the callbacks will have a different effect,
% depending on whether we are currently inside a layout scope or not
% (if no graph drawing scope is open, we are
% not inside a layout). If we are not inside a layout scope (or if the
% layout scope has been interrupted), the code will issue a
% \pgfgdbeginscope command in the opening code and a corresponding
% scope ending command in the closing code. Next, the two code pieces
% always contain \pgfgdbeginlayout and \pgfgdendlayout.
%
% Note that the "@request scope and layout" key will not immediately
% trigger a layout scope to be created; rather, the TikZ callback will
% call it only at the beginning of the scope, which will be after
% other options in the current list of options have been parsed. So,
% when you write \graph [binary tree layout, significant sep=2em] ...,
% the "significant sep" option has an effect despite being given
% *after* the "@request scope and layout" key since the actual opening
% of the scope happens only before the "..." part is parsed.
\pgfgdset{@request scope and layout/.code=\pgfgd@requestcallback{\pgfgdbeginrequest}{\pgfgdendrequest}}%
\def\pgfgd@requestcallback#1#2{%
#1\def\pgf@gd@after@request{#2\egroup}\bgroup\aftergroup\pgf@gd@after@request%
}% Default for basic layer
\def\pgfgdbeginrequest{%
\ifpgfgdlayoutscopeactive%
\else%
\expandafter\pgfgdbeginscope%
\fi%
\pgfgdbeginlayout%
}%
\def\pgfgdendrequest{%
\pgfgdendlayout%
\ifpgfgdlayoutscopeactive%
\else%
\expandafter\pgfgdendscope%
\fi%
}%
\newif\ifpgfgdlayoutscopeactive
% Set the request callback
%
% #1 = A macro
%
% Description:
%
% Sets the request callback as described in the "@request scope and
% layout" key.
\def\pgfgdsetrequestcallback#1{\let\pgfgd@requestcallback#1}%
%
% An if that is true exactly if we are inside a graph drawing scope
%
\newif\ifpgfgdgraphdrawingscopeactive
% Begins a new graph drawing scope
%
% Description:
%
% Inside a graph drawing scope, all pgf nodes that are newly created
% are automatically passed to the graph drawing engine. In contrast,
% edges have to be indicated explicitly using the macro \pgfgdedge
% (this is because it is somewhat unclear what, exactly, should count
% as an edge). Naturally, users typically will not call \pgfgdedge
% explicitly, but have styles and keys invoke it internally.
%
% Usage:
%
% \pgfgdset{algorithm=somealgorithm}
% \pgfgdbeginscope
% \pgfnode{rectangle}{center}{A}{A}{}
% \pgfnode{rectangle}{center}{B}{B}{}
% \pgfnode{rectangle}{center}{C}{C}{}
% \pgfgdedge{A}{B}{->}{}{}
% \pgfgdedge{B}{C}{->}{}{}
% \pgfgdedge{C}{A}{->}{}{}
% \pgfgdendscope
%
% Naturally, users will typically use TikZ's somewhat simpler syntax: '
%
% \tikz \graph [some algorithm] { A -> B -> C -> A };
\def\pgfgdbeginscope{%
\begingroup % Protecting scope
% get options
\directlua{
pgf.gd.interface.InterfaceToDisplay.beginGraphDrawingScope(\the\pgf@gd@parameter@stack@height)
}%
\begingroup % Inner scope, the actual nodes will be inserted after
% this scope has been closed
% Indicate that we are now inside a graph drawing scope
\pgfgdgraphdrawingscopeactivetrue
% Switch on late positioning
\pgfpositionnodelater{\pgf@gd@positionnode@callback}
% Switch on late edges
\pgfgd@latecallback%
% Kill transformations (will be added by the position now
% macros)
\pgftransformreset
}%
% The following is used to ensure that if we need to resume the graph
% drawing (through co-routines), we pass control back to TeX
% first. Otherwise, new text input levels are created and there may be
% only 15 of these...
\newif\ifpgfgdresumecoroutine
% Ends a graph drawing scope
%
% Description:
%
% This macro invokes the selected graph drawing algorithm and
% ships out all nodes within this scope
%
% See \pgfgdbeginscope
\def\pgfgdendscope{%
\pgfgdresumecoroutinefalse%
\directlua{
pgf.gd.interface.InterfaceToDisplay.runGraphDrawingAlgorithm()
}%
\pgfutil@loop%
\ifpgfgdresumecoroutine%
\pgfgdresumecoroutinefalse%
\directlua{
pgf.gd.interface.InterfaceToDisplay.resumeGraphDrawingCoroutine()
}%
\pgfutil@repeat%
\endgroup%
% Late positioning has ended
\directlua{pgf.gd.interface.InterfaceToDisplay.renderGraph()}%
\directlua{pgf.gd.interface.InterfaceToDisplay.endGraphDrawingScope()}%
\endgroup%
}%
% Hook into graph specification
%
% #1 = code
%
% Description:
%
% Allows you to specify code that should be active while the graph
% drawing engine collects the information concerning the graph, but
% which should no longer be active when the graph is rendered.
\def\pgfgdaddspecificationhook#1{
\expandafter\def\expandafter\pgfgd@latecallback\expandafter{\pgfgd@latecallback#1}
}%
\let\pgfgd@latecallback\pgfutil@empty
% Loading further libraries
% Include a graph drawing library file.
%
% #1 = List of names of library file.
%
% Description:
%
% This command includes a list of graph drawing library files. For
% each file X in the list, the file pgf.gd.X.lua is included using
% |require|.
%
% For the convenience of Context users, both round and square brackets
% are possible for the argument.
%
%
% Example:
%
% \usegdlibrary{trees}
% \usegdlibrary[force,circular]
\def\usegdlibrary{\pgfutil@ifnextchar[{\use@gdlibrary}{\use@@gdlibrary}}%}%
\def\use@gdlibrary[#1]{\use@@gdlibrary{#1}}%
\def\use@@gdlibrary#1{%
\edef\pgf@list{#1}%
\pgfutil@for\pgf@temp:=\pgf@list\do{%
\expandafter\pgfkeys@spdef\expandafter\pgf@temp\expandafter{\pgf@temp}%
\ifx\pgf@temp\pgfutil@empty
\else
\directlua{if not pgf_lookup_and_require('\pgf@temp') then
tex.print('\pgfutil@luaescapestring{\noexpand\pgferror{Graph drawing library '\pgf@temp' not found}}')
end}
\fi
}
}%
% LaTeX uses kpathsea for file lookup while ConTeXt uses its
% resolvers. Luckily, kpathsea is still accessible in ConTeXt in a
% subtable kpse.original which we use if kpse.find_file is nil.
{%
\catcode`\%=11
\directlua{
function pgf_lookup_and_require(name)
local sep = package.config:sub(1,1)
local function lookup(name)
local sub = name:gsub('%.',sep)
local find_file = context and
resolvers.findfile or
kpse.find_file
if find_file(sub, 'lua') then
require(name)
elseif find_file(sub, 'clua') then
collectgarbage('stop')
require(name)
collectgarbage('restart')
else
return false
end
return true
end
return
lookup('pgf.gd.' .. name .. '.library') or
lookup('pgf.gd.' .. name) or
lookup(name .. '.library') or
lookup(name)
end
}
}%
%
% Ok, fire up the system by creating the binding!
%
\directlua{
require 'pgf.gd.interface.InterfaceToDisplay'
pgf.gd.interface.InterfaceToDisplay.bind(require 'pgf.gd.bindings.BindingToPGF')
}%
%
% Special setup for keys that are declared by the above libraries, but
% that have a special meaning on the display layer.
%
\pgfkeys{/graph drawing/nodes behind edges/.append code=\csname pgf@gd@nodes@behind@edges#1\endcsname}%
\pgfkeys{/graph drawing/nodes behind edges/.default=true}%
\endinput