Copied 02a820ebdec93aac25e93945b16a6360c6ac7d43 from gitlab graphviz.
authorStephen C North <scnorth@gmail.com>
Wed, 4 Jul 2018 11:20:40 +0000 (07:20 -0400)
committerStephen C North <scnorth@gmail.com>
Wed, 4 Jul 2018 11:20:40 +0000 (07:20 -0400)
This add attribute TBbalance={min,max} to push tree nodes with slack as low or high as possible and sets DPI to 72 instead of 96 for quartz. Hope that's ok.

lib/common/ns.c
lib/dotgen/fastgr.c
plugin/quartz/gvrender_quartz.c

index b06344672a193d9b804b3aefe744d744ead08795..eaf435db57b0a3d0ad132ff9d17c5eabe2e22476 100644 (file)
@@ -670,12 +670,22 @@ static void LR_balance(void)
     freeTreeList (G);
 }
 
+static int decreasingrankcmpf(node_t **n0, node_t **n1) {
+  return ND_rank(*n1) - ND_rank(*n0);
+}
+
+static int increasingrankcmpf(node_t **n0, node_t **n1) {
+  return ND_rank(*n0) - ND_rank(*n1);
+}
+
 static void TB_balance(void)
 {
     node_t *n;
     edge_t *e;
-    int i, low, high, choice, *nrank;
+    int i, ii, low, high, choice, *nrank;
     int inweight, outweight;
+    int adj = 0;
+    char *s;
 
     scan_and_normalize();
 
@@ -683,37 +693,60 @@ static void TB_balance(void)
     nrank = N_NEW(Maxrank + 1, int);
     for (i = 0; i <= Maxrank; i++)
        nrank[i] = 0;
-    for (n = GD_nlist(G); n; n = ND_next(n))
-       if (ND_node_type(n) == NORMAL)
-           nrank[ND_rank(n)]++;
-    for (n = GD_nlist(G); n; n = ND_next(n)) {
-       if (ND_node_type(n) != NORMAL)
-           continue;
-       inweight = outweight = 0;
-       low = 0;
-       high = Maxrank;
-       for (i = 0; (e = ND_in(n).list[i]); i++) {
-           inweight += ED_weight(e);
-           low = MAX(low, ND_rank(agtail(e)) + ED_minlen(e));
-       }
-       for (i = 0; (e = ND_out(n).list[i]); i++) {
-           outweight += ED_weight(e);
-           high = MIN(high, ND_rank(aghead(e)) - ED_minlen(e));
-       }
-       if (low < 0)
-           low = 0;            /* vnodes can have ranks < 0 */
-       if (inweight == outweight) {
-           choice = low;
-           for (i = low + 1; i <= high; i++)
-               if (nrank[i] < nrank[choice])
-                   choice = i;
-           nrank[ND_rank(n)]--;
-           nrank[choice]++;
-           ND_rank(n) = choice;
-       }
-       free_list(ND_tree_in(n));
-       free_list(ND_tree_out(n));
-       ND_mark(n) = FALSE;
+    if (s = agget(G,"TBbalance")) {
+         if (streq(s,"min")) adj = 1;
+         else if (streq(s,"max")) adj = 2;
+         if (adj) for (n = GD_nlist(G); n; n = ND_next(n))
+              if (ND_node_type(n) == NORMAL)
+                if (ND_out(n).size == 0)
+                   ND_rank(n) = ((adj == 1)? Minrank : Maxrank);
+    }
+    for (ii = 0, n = GD_nlist(G); n; ii++, n = ND_next(n)) {
+      Tree_node.list[ii] = n;
+    }
+    Tree_node.size = ii;
+    qsort(Tree_node.list, Tree_node.size, sizeof(Tree_node.list[0]),
+        adj > 1? decreasingrankcmpf : increasingrankcmpf);
+    for (i = 0; i < Tree_node.size; i++) {
+        n = Tree_node.list[i];
+        if (ND_node_type(n) == NORMAL)
+          nrank[ND_rank(n)]++;
+    }
+    for (ii = 0; ii < Tree_node.size; ii++) {
+      n = Tree_node.list[ii];
+      if (ND_node_type(n) != NORMAL)
+        continue;
+      inweight = outweight = 0;
+      low = 0;
+      high = Maxrank;
+      for (i = 0; (e = ND_in(n).list[i]); i++) {
+        inweight += ED_weight(e);
+        low = MAX(low, ND_rank(agtail(e)) + ED_minlen(e));
+      }
+      for (i = 0; (e = ND_out(n).list[i]); i++) {
+        outweight += ED_weight(e);
+        high = MIN(high, ND_rank(aghead(e)) - ED_minlen(e));
+      }
+      if (low < 0)
+        low = 0;               /* vnodes can have ranks < 0 */
+      if (adj) {
+        if (inweight == outweight)
+            ND_rank(n) = (adj == 1? low : high);
+      }
+      else {
+                if (inweight == outweight) {
+                    choice = low;
+                    for (i = low + 1; i <= high; i++)
+                        if (nrank[i] < nrank[choice])
+                            choice = i;
+                    nrank[ND_rank(n)]--;
+                    nrank[choice]++;
+                    ND_rank(n) = choice;
+                }
+      }
+      free_list(ND_tree_in(n));
+      free_list(ND_tree_out(n));
+      ND_mark(n) = FALSE;
     }
     free(nrank);
 }
index 1dd763c9cd638b95f1758a0e406b31932d00415a..03d0396b19401ec5e4bc3889ec106c059fff3d48 100644 (file)
@@ -237,12 +237,11 @@ void delete_fast_node(graph_t * g, node_t * n)
        GD_nlist(g) = ND_next(n);
 }
 
-node_t *virtual_node(graph_t * g)
+node_t *named_virtual_node(graph_t * g, char *s)
 {
     node_t *n;
 
     n = NEW(node_t);
-//  agnameof(n) = "virtual";
     AGTYPE(n) = AGNODE;
     n->base.data = (Agrec_t*)NEW(Agnodeinfo_t);
     n->root = agroot(g);
@@ -250,6 +249,7 @@ node_t *virtual_node(graph_t * g)
     ND_lw(n) = ND_rw(n) = 1;
     ND_ht(n) = 1;
     ND_UF_size(n) = 1;
+    if (s) ND_alg(n) = s;
     alloc_elist(4, ND_in(n));
     alloc_elist(4, ND_out(n));
     fast_node(g, n);
@@ -257,6 +257,11 @@ node_t *virtual_node(graph_t * g)
     return n;
 }
 
+node_t *virtual_node(graph_t * g)
+{
+  return named_virtual_node(g,0);
+}
+
 void flat_edge(graph_t * g, edge_t * e)
 {
     elist_append(e, ND_flat_out(agtail(e)));
index f0995ff3da4f68d8e5b13b4c31f553c3ea470767..fb3c66e290b84c341c02fd1a78f1b59f00683c79 100644 (file)
@@ -475,7 +475,7 @@ static gvdevice_features_t device_features_quartz = {
     GVDEVICE_BINARY_FORMAT | GVDEVICE_DOES_TRUECOLOR,  /* flags */
     {0., 0.},                  /* default margin - points */
     {0., 0.},                  /* default page width, height - points */
-    {96., 96.}                 /* dpi */
+    {72., 72.}                 /* dpi */
 };
 #endif