]> granicus.if.org Git - graphviz/commitdiff
Similar fix that we did for dot: cgraph does not have a flat namespace for subgraphs,
authorEmden Gansner <erg@research.att.com>
Fri, 11 Nov 2011 19:34:26 +0000 (14:34 -0500)
committerEmden Gansner <erg@research.att.com>
Fri, 11 Nov 2011 19:34:26 +0000 (14:34 -0500)
so we need to construct an explicit map from name to cluster. Pulled out the code we
used in dot and moved it to utils.c.

lib/common/utils.c
lib/common/utils.h
lib/dotgen/compound.c

index 4ff6bdc2c54b7edbfc3efce6237c4bad3bc3358f..966d97a1219ce17be5cb08a36bd53164de9495e0 100644 (file)
@@ -1137,11 +1137,17 @@ static item *mapEdge(Dt_t * map, edge_t * e)
 #ifndef WITH_CGRAPH
 #define MAPC(n) (strncmp((n)->name,"cluster",7)?NULL:agfindsubg((n)->graph, (n)->name))
 #else /* WITH_CGRAPH */
-#define MAPC(n) (strncmp(agnameof(n),"cluster",7)?NULL:agsubg(agraphof(n), agnameof(n),0))
+#define MAPC(n) (strncmp(agnameof(n),"cluster",7)?NULL:findCluster(cmap,agnameof(n)))
 #endif /* WITH_CGRAPH */
 
+
+#ifdef WITH_CGRAPH
+static void
+checkCompound(edge_t * e, graph_t * clg, agxbuf * xb, Dt_t * map, Dt_t* cmap)
+#else
 static void
 checkCompound(edge_t * e, graph_t * clg, agxbuf * xb, Dt_t * map)
+#endif
 {
     graph_t *tg;
     graph_t *hg;
@@ -1221,6 +1227,9 @@ int processClusterEdges(graph_t * g)
     graph_t *clg;
     agxbuf xb;
     Dt_t *map;
+#ifdef WITH_CGRAPH
+    Dt_t *cmap = mkClustMap (g);
+#endif
     unsigned char buf[SMALLBUF];
 
     map = dtopen(&mapDisc, Dtoset);
@@ -1234,7 +1243,11 @@ int processClusterEdges(graph_t * g)
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        if (IS_CLUST_NODE(n)) continue;
        for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
+#ifndef WITH_CGRAPH
            checkCompound(e, clg, &xb, map);
+#else
+           checkCompound(e, clg, &xb, map, cmap);
+#endif
        }
     }
     agxbfree(&xb);
@@ -1247,6 +1260,9 @@ int processClusterEdges(graph_t * g)
     agclose(clg);
     if (rv)
        SET_CLUST_EDGE(g);
+#ifdef WITH_CGRAPH
+    dtclose(cmap);
+#endif
     return rv;
 }
 
@@ -1947,3 +1963,74 @@ double drand48(void)
     return d;
 }
 #endif
+#ifdef WITH_CGRAPH
+typedef struct {
+    Dtlink_t link;
+    char* name;
+    Agraph_t* clp;
+} clust_t;
+
+static void free_clust (Dt_t* dt, clust_t* clp, Dtdisc_t* disc)
+{
+    free (clp);
+}
+
+static Dtdisc_t strDisc = {
+    offsetof(clust_t,name),
+    -1,
+    offsetof(clust_t,link),
+    NIL(Dtmake_f),
+    (Dtfree_f)free_clust,
+    NIL(Dtcompar_f),
+    NIL(Dthash_f),
+    NIL(Dtmemory_f),
+    NIL(Dtevent_f)
+};
+
+static void fillMap (Agraph_t* g, Dt_t* map)
+{
+    Agraph_t* cl;
+    int c;
+    char* s;
+    clust_t* ip;
+
+    for (c = 1; c <= GD_n_cluster(g); c++) {
+       cl = GD_clust(g)[c];
+       s = agnameof(cl);
+       if (dtmatch (map, &s)) {
+           agerr(AGWARN, "Two clusters named %s - the second will be ignored\n", s);
+       }
+       else {
+           ip = NEW(clust_t);
+           ip->name = s;
+           ip->clp = cl;
+           dtinsert (map, ip);
+       }
+       fillMap (cl, map);
+    }
+}
+
+/* mkClustMap:
+ * Generates a dictionary mapping cluster names to corresponding cluster.
+ * Used with cgraph as the latter does not support a flat namespace of clusters.
+ * Assumes G has already built a cluster tree using GD_n_cluster and GD_clust.
+ */
+Dt_t* mkClustMap (Agraph_t* g)
+{
+    Dt_t* map = dtopen (&strDisc, Dtoset);
+
+    fillMap (g, map);
+    
+    return map;
+}
+
+Agraph_t*
+findCluster (Dt_t* map, char* name)
+{
+    clust_t* clp = dtmatch (map, name);
+    if (clp)
+       return clp->clp;
+    else
+       return NULL;
+}
+#endif
index 28368a98736ff84d839be518167faa9b89d988f8..b922b4a56645badd98292e2d2245cd01b6d0ee44 100644 (file)
@@ -60,6 +60,8 @@ extern "C" {
     extern attrsym_t* safe_dcl(graph_t*, void*, char*, char*,
              attrsym_t * (*fun) (Agraph_t *, char *, char *));
 #else
+    extern Dt_t* mkClustMap (Agraph_t* g);
+    extern Agraph_t* findCluster (Dt_t* map, char* name);
     extern attrsym_t* safe_dcl(graph_t * g, int obj_kind, char *name, char *def);
 #endif
 
index d42656675064d659619c519b9e760ec7b5d9aae5..25d659aac5dd6f125e685ce39538c2bb94d51505 100644 (file)
@@ -88,93 +88,31 @@ static int inBoxf(pointf p, boxf * bb)
     return INSIDE(p, *bb);
 }
 
-#ifdef WITH_CGRAPH
-typedef struct {
-    Dtlink_t link;
-    char* name;
-    Agraph_t* clp;
-} clust_t;
-
-static void free_clust (Dt_t* dt, clust_t* clp, Dtdisc_t* disc)
-{
-    free (clp);
-}
-
-static Dtdisc_t strDisc = {
-    offsetof(clust_t,name),
-    -1,
-    offsetof(clust_t,link),
-    NIL(Dtmake_f),
-    (Dtfree_f)free_clust,
-    NIL(Dtcompar_f),
-    NIL(Dthash_f),
-    NIL(Dtmemory_f),
-    NIL(Dtevent_f)
-};
-
-static void fillMap (Agraph_t* g, Dt_t* map)
-{
-    Agraph_t* cl;
-    int c;
-    char* s;
-    clust_t* ip;
-
-    for (c = 1; c <= GD_n_cluster(g); c++) {
-       cl = GD_clust(g)[c];
-       s = agnameof(cl);
-       if (dtmatch (map, &s)) {
-           agerr(AGWARN, "Two clusters named %s - the second will be ignored\n", s);
-       }
-       else {
-           ip = NEW(clust_t);
-           ip->name = s;
-           ip->clp = cl;
-           dtinsert (map, ip);
-       }
-       fillMap (cl, map);
-    }
-}
-
-static Dt_t* mkClustMap (Agraph_t* g)
-{
-    Dt_t* map = dtopen (&strDisc, Dtoset);
-
-    fillMap (g, map);
-    
-    return map;
-}
-
 /* getCluster:
  * Returns subgraph of g with given name.
  * Returns NULL if no name is given, or subgraph of
  * that name does not exist.
  */
+#ifdef WITH_CGRAPH
 static graph_t *getCluster(graph_t * g, char *cluster_name, Dt_t* map)
-{
-    clust_t* clp;
-
-    if (!cluster_name || (*cluster_name == '\0'))
-       return NULL;
-    clp = dtmatch (map, cluster_name);
-    if (clp == NULL) {
-       agerr(AGWARN, "cluster named %s not found\n", cluster_name);
-       return NULL;
-    }
-    else return clp->clp;
-}
 #else
 static graph_t *getCluster(graph_t * g, char *cluster_name)
+#endif
 {
-    graph_t *sg;
+    Agraph_t* sg;
 
     if (!cluster_name || (*cluster_name == '\0'))
        return NULL;
+#ifdef WITH_CGRAPH
+    sg = findCluster (map, cluster_name);
+#else
     sg = agfindsubg(g, cluster_name);
-    if (sg == NULL)
+#endif
+    if (sg == NULL) {
        agerr(AGWARN, "cluster named %s not found\n", cluster_name);
+    }
     return sg;
 }
-#endif
 
 /* The following functions are derived from pp. 411-415 (pp. 791-795)
  * of Graphics Gems. In the code there, they use a SGN function to