Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
dotinit.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <assert.h>
12#include <cgraph/agxbuf.h>
13#include <cgraph/alloc.h>
14#include <cgraph/streq.h>
15#include <limits.h>
16#include <time.h>
17#include <dotgen/dot.h>
18#include <pack/pack.h>
19#include <dotgen/aspect.h>
20#include <stdbool.h>
21#include <stddef.h>
22#include <stdint.h>
23
24static void
26{
27 graph_t* subg;
28
29 if ((g != agroot(g)))
30 agbindrec(g, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
31 if (g == droot)
32 GD_dotroot(agroot(g)) = droot;
33
34 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
35 dot_init_subg(subg, droot);
36 }
37}
38
39
40static void
42{
43 agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true); //graph custom data
46 alloc_elist(4, ND_in(n));
47 alloc_elist(4, ND_out(n));
50 alloc_elist(2, ND_other(n));
51 ND_UF_size(n) = 1;
52}
53
54static void
56{
57 char *tailgroup, *headgroup;
58 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //graph custom data
60
61 ED_weight(e) = late_int(e, E_weight, 1, 0);
62 tailgroup = late_string(agtail(e), N_group, "");
63 headgroup = late_string(aghead(e), N_group, "");
64 ED_count(e) = ED_xpenalty(e) = 1;
65 if (tailgroup[0] && (tailgroup == headgroup)) {
67 ED_weight(e) *= 100;
68 }
69 if (nonconstraint_edge(e)) {
70 ED_xpenalty(e) = 0;
71 ED_weight(e) = 0;
72 }
73
74 {
75 int showboxes = late_int(e, E_showboxes, 0, 0);
76 if (showboxes > UCHAR_MAX) {
77 showboxes = UCHAR_MAX;
78 }
79 ED_showboxes(e) = (unsigned char)showboxes;
80 }
81 ED_minlen(e) = late_int(e, E_minlen, 1, 0);
82}
83
84void
86{
87 node_t *n;
88 edge_t *e;
89
90 for (n = agfstnode(g); n; n = agnxtnode(g, n))
92 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
93 for (e = agfstout(g, n); e; e = agnxtout(g, e))
95 }
96}
97
98static void
100{
101 free_list(ND_in(n));
102 free_list(ND_out(n));
108 if (ND_shape(n))
109 ND_shape(n)->fns->freefn(n);
110 agdelrec(n, "Agnodeinfo_t");
111}
112
114{
115 edge_t *e;
116
117 for (size_t i = ND_in(n).size - 1; i != SIZE_MAX; i--) {
118 e = ND_in(n).list[i];
120 free(e->base.data);
121 free(e);
122 }
123 for (size_t i = ND_out(n).size - 1; i != SIZE_MAX; i--) {
124 e = ND_out(n).list[i];
126 free(e->base.data);
127 free(e);
128 }
129}
130
132{
133 node_t *next_vn;
134
135 while (vn) {
136 next_vn = ND_next(vn);
138 if (ND_node_type(vn) == VIRTUAL) {
139 free_list(ND_out(vn));
140 free_list(ND_in(vn));
141 free(vn->base.data);
142 free(vn);
143 }
144 vn = next_vn;
145 }
146}
147
148static void
150{
151 int i;
152 graph_t *subg;
153 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
154 dot_cleanup_graph(subg);
155 }
156 if (! agbindrec(g, "Agraphinfo_t", 0, true)) return;
157 free (GD_clust(g));
158 free (GD_rankleader(g));
159
160 free_list(GD_comp(g));
161 if (GD_rank(g)) {
162 for (i = GD_minrank(g); i <= GD_maxrank(g); i++)
163 free(GD_rank(g)[i].av);
164 if (GD_minrank(g) == -1)
165 free(GD_rank(g)-1);
166 else
167 free(GD_rank(g));
168 }
169 if (g != agroot(g)) {
170 free_label (GD_label(g));
171 }
172}
173
174/* delete the layout (but retain the underlying graph) */
176{
177 node_t *n;
178 edge_t *e;
179
181 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
182 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
184 }
186 }
188}
189
190#ifdef DEBUG
191int
192fastn (graph_t * g)
193{
194 node_t* u;
195 int cnt = 0;
196 for (u = GD_nlist(g); u; u = ND_next(u)) cnt++;
197 return cnt;
198}
199
200#if DEBUG > 1
201static void
202dumpRanks (graph_t * g)
203{
204 int i, j;
205 node_t* u;
206 rank_t *rank = GD_rank(g);
207 int rcnt = 0;
208 for (i = GD_minrank(g); i <= GD_maxrank(g); i++) {
209 fprintf (stderr, "[%d] :", i);
210 for (j = 0; j < rank[i].n; j++) {
211 u = rank[i].v[j];
212 rcnt++;
213 if (streq(agnameof(u),"virtual"))
214 fprintf (stderr, " %x", u);
215 else
216 fprintf (stderr, " %s", agnameof(u));
217
218 }
219 fprintf (stderr, "\n");
220 }
221 fprintf (stderr, "count %d rank count = %d\n", fastn(g), rcnt);
222}
223#endif
224#endif
225
226
227static void
229{
230 Agnode_t* v = NULL;
231 int j, rk = ND_rank(n);
232
233 for (j = 0; j < GD_rank(g)[rk].n; j++) {
234 v = GD_rank(g)[rk].v[j];
235 if (v == n) {
236 for (j++; j < GD_rank(g)[rk].n; j++) {
237 GD_rank(g)[rk].v[j-1] = GD_rank(g)[rk].v[j];
238 }
239 GD_rank(g)[rk].n--;
240 break;
241 }
242 }
243 assert (v == n); /* if found */
244}
245
246/* removeFill:
247 * This removes all of the fill nodes added in mincross.
248 * It appears to be sufficient to remove them only from the
249 * rank array and fast node list of the root graph.
250 */
251static void
253{
254 Agnode_t* n;
255 Agnode_t* nxt;
256 Agraph_t* sg = agsubg (g, "_new_rank", 0);
257
258 if (!sg) return;
259 for (n = agfstnode(sg); n; n = nxt) {
260 nxt = agnxtnode(sg, n);
261 delete_fast_node (g, n);
262 remove_from_rank (g, n);
264 agdelnode(g, n);
265 }
266 agdelsubg (g, sg);
267
268}
269
270#define agnodeattr(g,n,v) agattr(g,AGNODE,n,v)
271
272static void
273attach_phase_attrs (Agraph_t * g, int maxphase)
274{
275 Agsym_t* rk = agnodeattr(g,"rank","");
276 Agsym_t* order = agnodeattr(g,"order","");
277 Agnode_t* n;
278 agxbuf buf = {0};
279
280 for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
281 if (maxphase >= 1) {
282 agxbprint(&buf, "%d", ND_rank(n));
283 agxset(n, rk, agxbuse(&buf));
284 }
285 if (maxphase >= 2) {
286 agxbprint(&buf, "%d", ND_order(n));
287 agxset(n, order, agxbuse(&buf));
288 }
289 }
290 agxbfree(&buf);
291}
292
293static void dotLayout(Agraph_t * g)
294{
295 int maxphase = late_int(g, agfindgraphattr(g,"phase"), -1, 1);
296
298 setAspect(g);
299
300 dot_init_subg(g,g);
302
303 dot_rank(g);
304 if (maxphase == 1) {
305 attach_phase_attrs (g, 1);
306 return;
307 }
308 dot_mincross(g);
309 if (maxphase == 2) {
310 attach_phase_attrs (g, 2);
311 return;
312 }
313 dot_position(g);
314 if (maxphase == 3) {
315 attach_phase_attrs (g, 2); /* positions will be attached on output */
316 return;
317 }
318 if (GD_flags(g) & NEW_RANK)
319 removeFill (g);
320 dot_sameports(g);
321 dot_splines(g);
322 if (mapbool(agget(g, "compound")))
324}
325
326static void
328{
329 agbindrec(sg, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
330 GD_drawing(sg) = gv_alloc(sizeof(layout_t));
331 GD_drawing(sg)->quantum = GD_drawing(g)->quantum;
332 GD_drawing(sg)->dpi = GD_drawing(g)->dpi;
333 GD_gvc(sg) = GD_gvc (g);
334 GD_charset(sg) = GD_charset (g);
335 GD_rankdir2(sg) = GD_rankdir2 (g);
336 GD_nodesep(sg) = GD_nodesep(g);
337 GD_ranksep(sg) = GD_ranksep(g);
338 GD_fontnames(sg) = GD_fontnames(g);
339}
340
341/* attachPos:
342 * the packing library assumes all units are in inches stored in ND_pos, so we
343 * have to copy the position info there.
344 */
345static void
347{
348 node_t* np;
349 double* ps = gv_calloc(2 * agnnodes(g), sizeof(double));
350
351 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
352 ND_pos(np) = ps;
353 ps[0] = PS2INCH(ND_coord(np).x);
354 ps[1] = PS2INCH(ND_coord(np).y);
355 ps += 2;
356 }
357}
358
359/* resetCoord:
360 * Store new position info from pack library call, stored in ND_pos in inches,
361 * back to ND_coord in points.
362 */
363static void
365{
366 node_t* np = agfstnode(g);
367 double* sp = ND_pos(np);
368 double* ps = sp;
369
370 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
371 ND_pos(np) = 0;
372 ND_coord(np).x = INCH2PS(ps[0]);
373 ND_coord(np).y = INCH2PS(ps[1]);
374 ps += 2;
375 }
376 free (sp);
377}
378
379static void
381{
382 int nclust, j;
383 Agraph_t* cg;
384
385 agbindrec(cl, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
386 GD_bb(cl) = GD_bb(scl);
387 GD_label_pos(cl) = GD_label_pos(scl);
388 memcpy(GD_border(cl), GD_border(scl), 4*sizeof(pointf));
389 nclust = GD_n_cluster(cl) = GD_n_cluster(scl);
390 GD_clust(cl) = gv_calloc(nclust + 1, sizeof(Agraph_t*));
391 for (j = 1; j <= nclust; j++) {
392 cg = mapClust(GD_clust(scl)[j]);
393 GD_clust(cl)[j] = cg;
394 copyCluster (GD_clust(scl)[j], cg);
395 }
396 /* transfer cluster label to original cluster */
397 GD_label(cl) = GD_label(scl);
398 GD_label(scl) = NULL;
399}
400
401/* copyClusterInfo:
402 * Copy cluster tree and info from components to main graph.
403 * Note that the original clusters have no Agraphinfo_t at this time.
404 */
405static void copyClusterInfo(size_t ncc, Agraph_t **ccs, Agraph_t *root) {
406 int j, nclust = 0;
407 Agraph_t* sg;
408 Agraph_t* cg;
409
410 for (size_t i = 0; i < ncc; i++)
411 nclust += GD_n_cluster(ccs[i]);
412
413 GD_n_cluster(root) = nclust;
414 GD_clust(root) = gv_calloc(nclust + 1, sizeof(Agraph_t*));
415 nclust = 1;
416 for (size_t i = 0; i < ncc; i++) {
417 sg = ccs[i];
418 for (j = 1; j <= GD_n_cluster(sg); j++) {
419 cg = mapClust(GD_clust(sg)[j]);
420 GD_clust(root)[nclust++] = cg;
421 copyCluster (GD_clust(sg)[j], cg);
422 }
423 }
424}
425
426/* doDot:
427 * Assume g has nodes.
428 */
429static void doDot (Agraph_t* g)
430{
431 Agraph_t **ccs;
432 Agraph_t *sg;
433 pack_info pinfo;
434 int Pack = getPack(g, -1, CL_OFFSET);
435 pack_mode mode = getPackModeInfo (g, l_undef, &pinfo);
436 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
437
438 if (mode == l_undef && Pack < 0) {
439 /* No pack information; use old dot with components
440 * handled during layout
441 */
442 dotLayout(g);
443 } else {
444 /* fill in default values */
445 if (mode == l_undef)
446 pinfo.mode = l_graph;
447 else if (Pack < 0)
448 Pack = CL_OFFSET;
449 assert(Pack >= 0);
450 pinfo.margin = (unsigned)Pack;
451 pinfo.fixed = NULL;
452
453 /* components using clusters */
454 size_t ncc;
455 ccs = cccomps(g, &ncc, 0);
456 if (ncc == 1) {
457 dotLayout(g);
458 } else if (GD_drawing(g)->ratio_kind == R_NONE) {
459 pinfo.doSplines = true;
460
461 for (size_t i = 0; i < ncc; i++) {
462 sg = ccs[i];
463 initSubg (sg, g);
464 dotLayout (sg);
465 }
466 attachPos (g);
467 packSubgraphs(ncc, ccs, g, &pinfo);
468 resetCoord (g);
469 copyClusterInfo (ncc, ccs, g);
470 } else {
471 /* Not sure what semantics should be for non-trivial ratio
472 * attribute with multiple components.
473 * One possibility is to layout nodes, pack, then apply the ratio
474 * adjustment. We would then have to re-adjust all positions.
475 */
476 dotLayout(g);
477 }
478
479 for (size_t i = 0; i < ncc; i++) {
480 free (GD_drawing(ccs[i]));
481 dot_cleanup_graph(ccs[i]);
482 agdelete(g, ccs[i]);
483 }
484 free(ccs);
485 }
486}
487
489{
490 if (agnnodes(g)) doDot (g);
492}
493
495{
496 return GD_dotroot(agroot(p));
497}
498
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static char * agxbuse(agxbuf *xb)
Definition agxbuf.h:286
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
void setAspect(Agraph_t *g)
Definition aspect.c:30
bool nonconstraint_edge(edge_t *e)
Definition class1.c:20
bool mapbool(const char *p)
Definition utils.c:336
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1443
char * late_string(void *obj, attrsym_t *attr, char *defaultValue)
Definition utils.c:78
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
Definition utils.c:33
void common_init_node(node_t *n)
Definition utils.c:422
void common_init_edge(edge_t *e)
Definition utils.c:505
void gv_nodesize(node_t *n, bool flip)
Definition utils.c:1556
void dot_compoundEdges(graph_t *g)
Definition compound.c:458
#define EDGETYPE_SPLINE
Definition const.h:253
#define CL_OFFSET
Definition const.h:151
#define NEW_RANK
Definition const.h:257
#define VIRTUAL
Definition const.h:25
#define CL_CROSS
Definition const.h:153
mode
Definition cvtgxl.c:33
static void dot_init_subg(graph_t *g, graph_t *droot)
Definition dotinit.c:25
static void dotLayout(Agraph_t *g)
Definition dotinit.c:293
static void dot_cleanup_node(node_t *n)
Definition dotinit.c:99
Agraph_t * dot_root(void *p)
Definition dotinit.c:494
static void free_virtual_edge_list(node_t *n)
Definition dotinit.c:113
static void attach_phase_attrs(Agraph_t *g, int maxphase)
Definition dotinit.c:273
static void removeFill(Agraph_t *g)
Definition dotinit.c:252
static void dot_init_node(node_t *n)
Definition dotinit.c:41
static void copyClusterInfo(size_t ncc, Agraph_t **ccs, Agraph_t *root)
Definition dotinit.c:405
void dot_layout(Agraph_t *g)
Definition dotinit.c:488
void dot_init_node_edge(graph_t *g)
Definition dotinit.c:85
static void dot_cleanup_graph(graph_t *g)
Definition dotinit.c:149
static void resetCoord(Agraph_t *g)
Definition dotinit.c:364
static void free_virtual_node_list(node_t *vn)
Definition dotinit.c:131
static void doDot(Agraph_t *g)
Definition dotinit.c:429
void dot_cleanup(graph_t *g)
Definition dotinit.c:175
static void initSubg(Agraph_t *sg, Agraph_t *g)
Definition dotinit.c:327
static void copyCluster(Agraph_t *scl, Agraph_t *cl)
Definition dotinit.c:380
#define agnodeattr(g, n, v)
Definition dotinit.c:270
static void attachPos(Agraph_t *g)
Definition dotinit.c:346
static void dot_init_edge(edge_t *e)
Definition dotinit.c:55
static void remove_from_rank(Agraph_t *g, Agnode_t *n)
Definition dotinit.c:228
void delete_fast_node(Agraph_t *, Agnode_t *)
Definition fastgr.c:191
void dot_mincross(Agraph_t *)
Definition mincross.c:350
void dot_sameports(Agraph_t *)
Definition sameport.c:39
void dot_splines(Agraph_t *)
Definition dotsplines.c:516
void dot_rank(Agraph_t *)
Definition rank.c:449
void delete_fast_edge(Agedge_t *)
Definition fastgr.c:108
void dot_position(Agraph_t *)
Definition position.c:125
#define PS2INCH(a_points)
Definition geom.h:70
#define INCH2PS(a_inches)
Definition geom.h:69
Agsym_t * N_group
Definition globals.h:88
Agsym_t * E_weight
Definition globals.h:91
Agsym_t * E_minlen
Definition globals.h:91
Agsym_t * E_showboxes
Definition globals.h:98
void free(void *)
#define SIZE_MAX
Definition gmlscan.c:347
node NULL
Definition grammar.y:149
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:199
int agnnodes(Agraph_t *g)
Definition graph.c:158
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:481
char * agget(void *obj, char *name)
Definition attr.c:442
#define ED_minlen(e)
Definition types.h:592
#define ED_showboxes(e)
Definition types.h:594
#define ED_xpenalty(e)
Definition types.h:601
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:23
#define ED_count(e)
Definition types.h:580
#define agtail(e)
Definition cgraph.h:889
#define ED_weight(e)
Definition types.h:603
#define aghead(e)
Definition cgraph.h:890
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:38
#define GD_minrank(g)
Definition types.h:384
#define agfindgraphattr(g, a)
Definition types.h:613
#define GD_rankdir2(g)
Definition types.h:376
#define GD_maxrank(g)
Definition types.h:382
#define GD_fontnames(g)
Definition types.h:402
#define GD_drawing(g)
Definition types.h:353
#define GD_border(g)
Definition types.h:359
#define GD_clust(g)
Definition types.h:360
#define GD_flags(g)
Definition types.h:365
#define GD_rank(g)
Definition types.h:395
#define GD_bb(g)
Definition types.h:354
#define GD_nlist(g)
Definition types.h:393
#define GD_label_pos(g)
Definition types.h:400
#define GD_n_cluster(g)
Definition types.h:389
#define GD_dotroot(g)
Definition types.h:361
#define GD_comp(g)
Definition types.h:362
#define GD_label(g)
Definition types.h:374
#define GD_nodesep(g)
Definition types.h:394
#define GD_charset(g)
Definition types.h:367
#define GD_gvc(g)
Definition types.h:355
#define GD_flip(g)
Definition types.h:378
#define GD_rankleader(g)
Definition types.h:396
#define GD_ranksep(g)
Definition types.h:397
#define ND_rank(n)
Definition types.h:523
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
#define ND_next(n)
Definition types.h:510
#define ND_other(n)
Definition types.h:514
#define ND_label(n)
Definition types.h:502
#define ND_flat_out(n)
Definition types.h:493
#define ND_node_type(n)
Definition types.h:511
int agdelnode(Agraph_t *g, Agnode_t *arg_n)
removes a node from a graph or subgraph.
Definition node.c:197
#define ND_order(n)
Definition types.h:513
#define ND_xlabel(n)
Definition types.h:503
#define ND_UF_size(n)
Definition types.h:487
#define ND_pos(n)
Definition types.h:520
#define ND_flat_in(n)
Definition types.h:492
#define ND_coord(n)
Definition types.h:490
#define ND_in(n)
Definition types.h:501
#define ND_shape(n)
Definition types.h:528
#define ND_out(n)
Definition types.h:515
Agraph_t * agraphof(void *obj)
Definition obj.c:184
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:19
Agraph_t * agroot(void *obj)
Definition obj.c:167
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Definition rec.c:88
int agdelrec(void *obj, const char *name)
deletes a named record from one object
Definition rec.c:136
Agraph_t * agfstsubg(Agraph_t *g)
Definition subg.c:77
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:82
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:57
int agdelsubg(Agraph_t *g, Agraph_t *sub)
Definition subg.c:98
void free_label(textlabel_t *p)
Definition labels.c:199
Agraph_t ** cccomps(Agraph_t *g, size_t *ncc, char *pfx)
Definition ccomps.c:484
Agraph_t * mapClust(Agraph_t *cl)
Definition ccomps.c:403
static int * ps
Definition lu.c:51
static int Pack
Definition neatoinit.c:51
int rank(graph_t *g, int balance, int maxiter)
Definition ns.c:997
pack_mode getPackModeInfo(Agraph_t *g, pack_mode dflt, pack_info *pinfo)
Definition pack.c:1220
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
Definition pack.c:1070
int getPack(Agraph_t *g, int not_def, int dflt)
Definition pack.c:1236
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
Definition pack.c:1253
support for connected components
pack_mode
Definition pack.h:55
@ l_undef
Definition pack.h:55
@ l_graph
Definition pack.h:55
@ l_node
Definition pack.h:55
void dotneato_postprocess(Agraph_t *g)
Definition postproc.c:693
void gv_cleanup_edge(Agedge_t *e)
Definition utils.c:1533
static double cg(SparseMatrix A, const double *precond, int n, int dim, double *x0, double *rhs, double tol, double maxit)
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
Agobj_t base
Definition cgraph.h:269
Agobj_t base
Definition cgraph.h:260
Agrec_t * data
stores programmer-defined data, access with AGDATA
Definition cgraph.h:212
graph or subgraph
Definition cgraph.h:425
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:639
pack_mode mode
Definition pack.h:72
bool doSplines
use splines in constructing graph shape
Definition pack.h:71
bool * fixed
Definition pack.h:73
unsigned int margin
Definition pack.h:70
#define free_list(L)
Definition types.h:272
#define alloc_elist(n, L)
Definition types.h:267
@ R_NONE
Definition types.h:215