Graphviz  2.41.20171026.1811
patchworkinit.c
Go to the documentation of this file.
1 /* $Id$Revision: */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include "patchwork.h"
15 #include "adjust.h"
16 #include "pack.h"
17 #include "neatoprocs.h"
18 
19 /* the following code shamelessly copied from lib/fdpgen/layout.c
20 and should be extracted and made into a common function */
21 
22 #define CL_CHUNK 10
23 
24 typedef struct {
25  graph_t **cl;
26  int sz;
27  int cnt;
28 } clist_t;
29 
30 static void initCList(clist_t * clist)
31 {
32  clist->cl = 0;
33  clist->sz = 0;
34  clist->cnt = 0;
35 }
36 
37 /* addCluster:
38  * Append a new cluster to the list.
39  * NOTE: cl[0] is empty. The clusters are in cl[1..cnt].
40  * Normally, we increase the array when cnt == sz.
41  * The test for cnt > sz is necessary for the first time.
42  */
43 static void addCluster(clist_t * clist, graph_t * subg)
44 {
45  clist->cnt++;
46  if (clist->cnt >= clist->sz) {
47  clist->sz += CL_CHUNK;
48  clist->cl = RALLOC(clist->sz, clist->cl, graph_t *);
49  }
50  clist->cl[clist->cnt] = subg;
51 }
52 
53 /* mkClusters:
54  * Attach list of immediate child clusters.
55  * NB: By convention, the indexing starts at 1.
56  * If pclist is NULL, the graph is the root graph or a cluster
57  * If pclist is non-NULL, we are recursively scanning a non-cluster
58  * subgraph for cluster children.
59  */
60 static void
61 mkClusters (graph_t * g, clist_t* pclist, graph_t* parent)
62 {
63  graph_t* subg;
64  clist_t list;
65  clist_t* clist;
66 
67  if (pclist == NULL) {
68  clist = &list;
69  initCList(clist);
70  }
71  else
72  clist = pclist;
73 
74  for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
75  if (!strncmp(agnameof(subg), "cluster", 7)) {
76  agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);
77 #ifdef FDP_GEN
78  GD_alg(subg) = (void *) NEW(gdata); /* freed in cleanup_subgs */
79  GD_ndim(subg) = GD_ndim(parent);
80  LEVEL(subg) = LEVEL(parent) + 1;
81  GPARENT(subg) = parent;
82 #endif
83  addCluster(clist, subg);
84  mkClusters(subg, NULL, subg);
85  }
86  else {
87  mkClusters(subg, clist, parent);
88  }
89  }
90  if (pclist == NULL) {
91  GD_n_cluster(g) = list.cnt;
92  if (list.cnt)
93  GD_clust(g) = RALLOC(list.cnt + 1, list.cl, graph_t*);
94  }
95 }
96 
97 static void patchwork_init_node(node_t * n)
98 {
99  agset(n,"shape","box");
100  /* common_init_node_opt(n,FALSE); */
101 }
102 
103 static void patchwork_init_edge(edge_t * e)
104 {
105  agbindrec(e, "Agedgeinfo_t", sizeof(Agnodeinfo_t), TRUE); // edge custom data
106  /* common_init_edge(e); */
107 }
108 
109 static void patchwork_init_node_edge(graph_t * g)
110 {
111  node_t *n;
112  edge_t *e;
113  int i = 0;
114  rdata* alg = N_NEW(agnnodes(g), rdata);
115 
116  GD_neato_nlist(g) = N_NEW(agnnodes(g) + 1, node_t *);
117  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
118  agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); // node custom data
119  ND_alg(n) = alg + i;
120  GD_neato_nlist(g)[i++] = n;
121  patchwork_init_node(n);
122 
123  for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
124  patchwork_init_edge(e);
125  }
126  }
127 }
128 
129 static void patchwork_init_graph(graph_t * g)
130 {
131  N_shape = agattr(g, AGNODE, "shape","box");
132  setEdgeType (g, ET_LINE);
133  /* GD_ndim(g) = late_int(g,agfindattr(g,"dim"),2,2); */
134  Ndim = GD_ndim(g) = 2; /* The algorithm only makes sense in 2D */
135  mkClusters(g, NULL, g);
136  patchwork_init_node_edge(g);
137 }
138 
139 /* patchwork_layout:
140  * The current version makes no use of edges, neither for a notion of connectivity
141  * nor during drawing.
142  */
144 {
145  patchwork_init_graph(g);
146 
147  if ((agnnodes(g) == 0) && (GD_n_cluster(g) == 0)) return;
148 
149  patchworkLayout (g);
150 
152 }
153 
154 static void patchwork_cleanup_graph(graph_t * g)
155 {
156  free(GD_neato_nlist(g));
157  if (g != agroot(g))
158  agclean(g, AGRAPH , "Agraphinfo_t");
159 }
160 
162 {
163  node_t *n;
164  edge_t *e;
165 
166  n = agfstnode(g);
167  if (!n) return;
168  free (ND_alg(n));
169  for (; n; n = agnxtnode(g, n)) {
170  for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
171  gv_cleanup_edge(e);
172  }
173  gv_cleanup_node(n);
174  }
175  patchwork_cleanup_graph(g);
176 }
void dotneato_postprocess(Agraph_t *g)
Definition: postproc.c:693
CGRAPH_API void agclean(Agraph_t *g, int kind, char *rec_name)
Definition: rec.c:238
void patchworkLayout(Agraph_t *g)
Definition: patchwork.c:275
#define RALLOC(size, ptr, type)
Definition: memory.h:42
Agsym_t * agattr(Agraph_t *g, int kind, char *name, char *value)
Definition: attr.c:324
#define N_NEW(n, t)
Definition: memory.h:36
#define GD_n_cluster(g)
Definition: types.h:396
graph_t ** cl
Definition: layout.c:281
void gv_cleanup_edge(Agedge_t *e)
Definition: utils.c:1947
CGRAPH_API Agraph_t * agfstsubg(Agraph_t *g)
Definition: subg.c:72
#define parent(i)
Definition: closest.c:88
CGRAPH_API Agraph_t * agroot(void *obj)
Definition: obj.c:169
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition: edge.c:25
int cnt
Definition: layout.c:283
#define CL_CHUNK
Definition: patchworkinit.c:22
CGRAPH_API Agraph_t * agnxtsubg(Agraph_t *subg)
Definition: subg.c:77
int agset(void *obj, char *name, char *value)
Definition: attr.c:455
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition: node.c:45
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
#define ET_LINE
Definition: const.h:271
#define GD_ndim(g)
Definition: types.h:398
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
Definition: node.c:38
#define GD_alg(g)
Definition: types.h:361
#define GD_clust(g)
Definition: types.h:364
#define AGNODE
Definition: cgraph.h:101
int sz
Definition: layout.c:282
void patchwork_layout(Agraph_t *g)
#define ND_alg(n)
Definition: types.h:490
#define NULL
Definition: logic.h:39
void gv_cleanup_node(Agnode_t *n)
Definition: utils.c:1959
CGRAPH_API int agnnodes(Agraph_t *g)
Definition: graph.c:162
EXTERN Agsym_t * N_shape
Definition: globals.h:95
CGRAPH_API void * agbindrec(void *obj, char *name, unsigned int size, int move_to_front)
Definition: rec.c:86
void setEdgeType(graph_t *g, int dflt)
Definition: utils.c:1802
void patchwork_cleanup(Agraph_t *g)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition: edge.c:40
#define GD_neato_nlist(g)
Definition: types.h:400
EXTERN int Ndim
Definition: globals.h:79
#define NEW(t)
Definition: memory.h:35
#define AGRAPH
Definition: cgraph.h:100
#define TRUE
Definition: cgraph.h:38