]> granicus.if.org Git - graphviz/commitdiff
Fix coding hole when packing disconnected components when clusters are used. We need to
authorEmden R. Gansner <erg@alum.mit.edu>
Wed, 7 May 2014 15:38:26 +0000 (11:38 -0400)
committerEmden R. Gansner <erg@alum.mit.edu>
Wed, 7 May 2014 15:38:26 +0000 (11:38 -0400)
recreate the cluster tree in the top-level graph, and copy position info from a cloned
cluster in a component to the real cluster in the top-level graph. (The clusters in a
component are really copies.);
use graph granularity by default when packing;
clean up layout info in the clusters before deleting them;
add comments on functions;
free cluster labels (this has never been done).

lib/dotgen/dotinit.c

index 1478535af522351be3948ebeee8d27813cef0c94..5b751be93af7b9171b29d92b9a1c9c8950e90ef9 100644 (file)
@@ -169,8 +169,10 @@ dot_cleanup_graph(graph_t * g)
        else
            free(GD_rank(g));
     }
-    if (g != agroot(g)) 
+    if (g != agroot(g)) {
+       free_label (GD_label(g));
        agdelrec(g,"Agraphinfo_t");
+    }
 }
 
 /* delete the layout (but retain the underlying graph) */
@@ -348,6 +350,10 @@ initSubg (Agraph_t* sg, Agraph_t* g)
     GD_fontnames(sg) = GD_fontnames(g);
 }
 
+/* attachPos:
+ * the packing library assumes all units are in inches stored in ND_pos, so we
+ * have to copy the position info there.
+ */
 static void
 attachPos (Agraph_t* g)
 {
@@ -362,6 +368,10 @@ attachPos (Agraph_t* g)
     }
 }
 
+/* resetCoord:
+ * Store new position info from pack library call, stored in ND_pos in inches,
+ * back to ND_coord in points.
+ */
 static void
 resetCoord (Agraph_t* g)
 {
@@ -378,6 +388,57 @@ resetCoord (Agraph_t* g)
     free (sp);
 }
 
+/* copyCluster:
+ */
+static void
+copyCluster (Agraph_t* scl, Agraph_t* cl)
+{
+    int nclust, j;
+    Agraph_t* cg;
+
+    agbindrec(cl, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);
+    GD_bb(cl) = GD_bb(scl);
+    GD_label_pos(cl) = GD_label_pos(scl);
+    memcpy(GD_border(cl), GD_border(scl), 4*sizeof(pointf));
+    nclust = GD_n_cluster(cl) = GD_n_cluster(scl);
+    GD_clust(cl) = N_NEW(nclust+1,Agraph_t*);
+    for (j = 1; j <= nclust; j++) {
+       cg = mapClust(GD_clust(scl)[j]);
+       GD_clust(cl)[j] = cg;
+       copyCluster (GD_clust(scl)[j], cg);
+    }
+    /* transfer cluster label to original cluster */
+    GD_label(cl) = GD_label(scl);
+    GD_label(scl) = NULL;
+}
+
+/* copyClusterInfo:
+ * Copy cluster tree and info from components to main graph.
+ * Note that the original clusters have no Agraphinfo_t at this time.
+ */
+static void
+copyClusterInfo (int ncc, Agraph_t** ccs, Agraph_t* root)
+{
+    int j, i, nclust = 0;
+    Agraph_t* sg;
+    Agraph_t* cg;
+
+    for (i = 0; i < ncc; i++) 
+       nclust += GD_n_cluster(ccs[i]);
+
+    GD_n_cluster(root) = nclust;
+    GD_clust(root) = N_NEW(nclust+1,Agraph_t*);
+    nclust = 1;
+    for (i = 0; i < ncc; i++) {
+       sg = ccs[i];
+       for (j = 1; j <= GD_n_cluster(sg); j++) {
+           cg = mapClust(GD_clust(sg)[j]);
+           GD_clust(root)[nclust++] = cg;
+           copyCluster (GD_clust(sg)[j], cg);
+       }
+    } 
+}
+
 /* doDot:
  * Assume g has nodes.
  */
@@ -400,7 +461,7 @@ static void doDot (Agraph_t* g)
     } else {
        /* fill in default values */
        if (mode == l_undef) 
-           pinfo.mode = l_node;
+           pinfo.mode = l_graph;
        else if (Pack < 0)
            Pack = CL_OFFSET;
        pinfo.margin = Pack;
@@ -421,6 +482,7 @@ static void doDot (Agraph_t* g)
            attachPos (g);
            packSubgraphs(ncc, ccs, g, &pinfo);
            resetCoord (g);
+           copyClusterInfo (ncc, ccs, g);
        } else {
            /* Not sure what semantics should be for non-trivial ratio
              * attribute with multiple components.
@@ -432,6 +494,7 @@ static void doDot (Agraph_t* g)
 
        for (i = 0; i < ncc; i++) {
            free (GD_drawing(ccs[i]));
+           dot_cleanup_graph(ccs[i]);
            agdelete(g, ccs[i]);
        }
        free(ccs);