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