--- /dev/null
+New layout: xxx
+
+Entry points:
+
+========================
+
+ void xxx_layout(Agraph_t * g)
+
+ Initialize the graph.
+ - If the algorithm will use the common edge routing code, it should
+ call setEdgeType (g, ...);
+
+ - For each node, call common_init_node and gv_nodesize.
+ If the algorithm will use spline_edges() to route the edges, the
+ node coordinates need to be stored in ND_pos, so this should be
+ allocated here.
+
+ - For each edge, call common_init_edge
+
+ - The algorithm should allocate whatever other data structures it
+ needs. This can involve fields in the A*info_t fields. In addition,
+ each of these fields contains a void* alg; subfield that the algorithm
+ can use the store additional data.
+ Once we move to cgraph, this will all be replace with
+ algorithm specific records.
+
+ Layout the graph. When finished, each node should have its coordinates
+ stored in points in ND_coord_i(n), each edge should have its layout
+ described in ED_spl(e). Note: If spline_edges() is used, the coordinates
+ in ND_pos will be correctly copied into ND_coord_i.
+
+ If the algorithm only works with connected components, the code can
+ use the pack library to get components, lay them out individually, and
+ pack them together based on user specifications. A typical schema is
+ given below. One can look at the code for twopi, circo, neato or fdp
+ for more detailed examples.
+
+ Agraph_t **ccs;
+ Agraph_t *sg;
+ Agnode_t *c = NULL;
+ int ncc;
+ int i;
+
+ ccs = ccomps(g, &ncc, 0);
+ if (ncc == 1) {
+ /* layout nodes of g */
+ adjustNodes(g); /* if you need to remove overlaps */
+ spline_edges(g); /* generic edge routing code */
+
+ } else {
+ pack_info pinfo;
+ pack_mode pmode = getPackMode(g, l_node);
+
+ for (i = 0; i < ncc; i++) {
+ sg = ccs[i];
+ /* layout sg */
+ adjustNodes(sg); /* if you need to remove overlaps */
+ }
+ spline_edges(g); /* generic edge routing */
+
+ /* initialize packing info, e.g. */
+ pinfo.margin = getPack(g, CL_OFFSET, CL_OFFSET);
+ pinfo.doSplines = 1;
+ pinfo.mode = pmode;
+ pinfo.fixed = 0;
+ packSubgraphs(ncc, ccs, g, &pinfo);
+ }
+ for (i = 0; i < ncc; i++) {
+ agdelete(g, ccs[i]);
+ }
+
+ free(ccs);
+
+ Be careful in laying of subgraphs if you rely on attributes that have
+ only been set in the root graph. With connected components, edges can
+ be added with each component, before packing (as above) or after the
+ components have been packed (see circo).
+
+ It good to check for trivial cases where the graph has 0 or 1 nodes,
+ or no edges.
+
+ At the end of xxx_layout, call
+
+ dotneato_postprocess(g);
+
+======================
+
+ void xxx_cleanup(Agraph_t * g)
+
+ Free up any resources allocated in the layout.
+
+ Finish with calls to gv_cleanup_node and gv_cleanup_edge for
+ each node and edge. This cleans up splines labels, ND_pos, shapes
+ and 0's out the A*info_t, so these have to occur last, but could be
+ part of explicit xxx_cleanup_node and xxx_cleanup_edge, if desired.
+ At the end, we usually include
+
+ if (g != g->root) memset(&(g->u), 0, sizeof(Agraphinfo_t));
+
+ libgvc does a final cleanup to the root graph, freeing any drawing,
+ freeing its label, and zeroing out Agraphinfo_t of the root graph.
+
+==================
+
+Most layouts use auxiliary routines similar to neato, so
+the entry points can be added in plugin/neato_layout
+
+Add to gvlayout_neato_layout.c:
+
+gvlayout_engine_t xxxgen_engine = {
+ xxx_layout,
+ xxx_cleanup,
+};
+
+and line
+
+ {LAYOUT_XXX, "xxx", 0, &xxxgen_engine, &neatogen_features},
+
+to gvlayout_neato_types and new emum
+
+ LAYOUT_XXX
+
+to layout_type in that file.
+
+Changes need to be made to any applications, such as gvedit, that
+statically know about layout algorithms.