]> granicus.if.org Git - graphviz/commitdiff
Allow prioritization of xlabels.
authorEmden Gansner <emdenrg@google.com>
Mon, 14 Dec 2015 20:45:44 +0000 (15:45 -0500)
committerEmden Gansner <emdenrg@google.com>
Mon, 14 Dec 2015 20:45:44 +0000 (15:45 -0500)
lib/common/postproc.c
lib/common/render.h

index 0a57f76492c87fc25d49909ffccdb59e9e1ef6b8..5e30687a076af815d0b2f33442d2dbb3d3a43176 100644 (file)
@@ -403,6 +403,35 @@ countClusterLabels (Agraph_t* g)
   /* True if edges geometries were computed and this edge has a geometry */
 #define HAVE_EDGE(ep) ((et != ET_NONE) && (ED_spl(ep) != NULL))
 
+typedef struct {
+    int* priorities;
+    object_t* p0;
+} xlabel_state;
+
+#if defined(WIN32) || defined(DARWIN)
+typedef int (*qsortr_cmpf) (void*, const void *, const void *);
+
+static int cmp_obj(xlabel_state* state, object_t* obj0, object_t* obj1)
+{
+    int prior0 = state->priorities[obj0 - state->p0];
+    int prior1 = state->priorities[obj1 - state->p0];
+    if (prior0 < prior1) return 1;
+    else if (prior0 > prior1) return -1;
+    else return 0;
+}
+#else
+typedef int (*qsortr_cmpf) (const void *, const void *, void*);
+
+static int cmp_obj(object_t* obj0, object_t* obj1, xlabel_state* state)
+{
+    int prior0 = state->priorities[obj0 - state->p0];
+    int prior1 = state->priorities[obj1 - state->p0];
+    if (prior0 < prior1) return 1;
+    else if (prior0 > prior1) return -1;
+    else return 0;
+}
+#endif
+
 static void addXLabels(Agraph_t * gp)
 {
     Agnode_t *np;
@@ -421,7 +450,13 @@ static void addXLabels(Agraph_t * gp)
     object_t* objp;
     xlabel_t* xlp;
     Agsym_t* force;
+    Agsym_t* edge_xlab_prior;
+    Agsym_t* node_xlab_prior;
+    Agsym_t* hd_edge_xlab_prior;
+    Agsym_t* tl_edge_xlab_prior;
+    int* priorities = NULL;
     int et = EDGE_TYPE(gp);
+    xlabel_state xlabs;
 
     if (!(GD_has_labels(gp) & NODE_XLABEL) &&
        !(GD_has_labels(gp) & EDGE_XLABEL) &&
@@ -471,29 +506,40 @@ static void addXLabels(Agraph_t * gp)
     n_lbls = n_nlbls + n_elbls;
     if (n_lbls == 0) return;
 
-    /* An object for each node, each positioned external label, any cluster label, 
-     * and all unset edge labels and xlabels.
+    /* An object for each node, each positioned external label, including dot edge labels, and
+     * any cluster label.
+     * An xlabel for all unset edge labels and xlabels.
      */
-    n_objs = agnnodes(gp) + n_set_lbls + n_clbls + n_elbls;
+    n_objs = agnnodes(gp) + n_set_lbls + n_clbls;
     objp = objs = N_NEW(n_objs, object_t);
     xlp = lbls = N_NEW(n_lbls, xlabel_t);
     bb.LL = pointfof(INT_MAX, INT_MAX);
     bb.UR = pointfof(-INT_MAX, -INT_MAX);
 
+    if ((node_xlab_prior = agattr(gp, AGNODE, "node_xlabel_prior", "")) ||
+        (hd_edge_xlab_prior = agattr(gp, AGEDGE, "head_edge_xlabel_prior", "")) ||
+        (tl_edge_xlab_prior = agattr(gp, AGEDGE, "tail_edge_xlabel_prior", "")) ||
+        (edge_xlab_prior = agattr(gp, AGEDGE, "edge_xlabel_prior", ""))) {
+       priorities = N_NEW(n_objs, int);
+        i = 0;
+    }
     for (np = agfstnode(gp); np; np = agnxtnode(gp, np)) {
 
        bb = addNodeObj (np, objp, bb);
        if ((lp = ND_xlabel(np))) {
            if (lp->set) {
                objp++;
+               i++;
                bb = addLabelObj (lp, objp, bb);
            }
            else {
+               priorities[i] = late_int (np, node_xlab_prior, 0, 0);
                addXLabel (lp, objp, xlp, 0, ur); 
                xlp++;
            }
        }
        objp++;
+       i++;
        for (ep = agfstout(gp, np); ep; ep = agnxtout(gp, ep)) {
            if ((lp = ED_label(ep))) {
                if (lp->set) {
@@ -501,6 +547,7 @@ static void addXLabels(Agraph_t * gp)
                }
                else if (HAVE_EDGE(ep)) {
                    addXLabel (lp, objp, xlp, 1, edgeMidpoint(gp, ep)); 
+                   priorities[i] = late_int (ep, edge_xlab_prior, 0, 0);
                    xlp++;
                }
                else {
@@ -509,6 +556,7 @@ static void addXLabels(Agraph_t * gp)
                    continue;
                }
                objp++;
+               i++;
            }
            if ((lp = ED_tail_label(ep))) {
                if (lp->set) {
@@ -516,6 +564,7 @@ static void addXLabels(Agraph_t * gp)
                }
                else if (HAVE_EDGE(ep)) {
                    addXLabel (lp, objp, xlp, 1, edgeTailpoint(ep)); 
+                   priorities[i] = late_int (ep, tl_edge_xlab_prior, 0, 0);
                    xlp++;
                }
                else {
@@ -524,6 +573,7 @@ static void addXLabels(Agraph_t * gp)
                    continue;
                }
                objp++;
+               i++;
            }
            if ((lp = ED_head_label(ep))) {
                if (lp->set) {
@@ -531,6 +581,7 @@ static void addXLabels(Agraph_t * gp)
                }
                else if (HAVE_EDGE(ep)) {
                    addXLabel (lp, objp, xlp, 1, edgeHeadpoint(ep)); 
+                   priorities[i] = late_int (ep, hd_edge_xlab_prior, 0, 0);
                    xlp++;
                }
                else {
@@ -539,6 +590,7 @@ static void addXLabels(Agraph_t * gp)
                    continue;
                }
                objp++;
+               i++;
            }
            if ((lp = ED_xlabel(ep))) {
                if (lp->set) {
@@ -546,6 +598,7 @@ static void addXLabels(Agraph_t * gp)
                }
                else if (HAVE_EDGE(ep)) {
                    addXLabel (lp, objp, xlp, 1, edgeMidpoint(gp, ep)); 
+                   priorities[i] = late_int (ep, edge_xlab_prior, 0, 0);
                    xlp++;
                }
                else {
@@ -554,6 +607,7 @@ static void addXLabels(Agraph_t * gp)
                    continue;
                }
                objp++;
+               i++;
            }
        }
     }
@@ -569,6 +623,18 @@ static void addXLabels(Agraph_t * gp)
 
     params.force = late_bool(gp, force, TRUE);
     params.bb = bb;
+
+    if (priorities) {
+       xlabs.priorities = priorities;
+       xlabs.p0 = objs;
+#if defined(WIN32)
+       qsort_s(objs, n_objs, sizeof(object_t), (qsortr_cmpf)cmp_obj, &xlabs);
+#else
+       qsort_r(objs, n_objs, sizeof(object_t), (qsortr_cmpf)cmp_obj, &xlabs);
+#endif
+       free (priorities);
+    }
+
     placeLabels(objs, n_objs, lbls, n_lbls, &params);
     if (Verbose)
        printData(objs, n_objs, lbls, n_lbls, &params);
index 66d385dea957cf55b62823f1f100d6f86547d288..5decf830e7afed38ffc5e286740b0b3a7302ee24 100644 (file)
@@ -25,7 +25,13 @@ extern "C" {
 #include <sys/types.h>
 #endif
 #ifdef HAVE_STDLIB_H
+#if !defined(WIN32) && !defined(DARWIN)
+#define __USE_GNU
 #include <stdlib.h>
+#undef __USE_GNU
+#else
+#include <stdlib.h>
+#endif
 #endif
 #ifdef HAVE_STDDEF_H
 #include <stddef.h>