From: Emden Gansner Date: Mon, 14 Dec 2015 20:45:44 +0000 (-0500) Subject: Allow prioritization of xlabels. X-Git-Tag: TRAVIS_CI_BUILD_EXPERIMENTAL~90 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f537b072e59350f96d55395ce5be6284a459586c;p=graphviz Allow prioritization of xlabels. --- diff --git a/lib/common/postproc.c b/lib/common/postproc.c index 0a57f7649..5e30687a0 100644 --- a/lib/common/postproc.c +++ b/lib/common/postproc.c @@ -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, ¶ms); if (Verbose) printData(objs, n_objs, lbls, n_lbls, ¶ms); diff --git a/lib/common/render.h b/lib/common/render.h index 66d385dea..5decf830e 100644 --- a/lib/common/render.h +++ b/lib/common/render.h @@ -25,7 +25,13 @@ extern "C" { #include #endif #ifdef HAVE_STDLIB_H +#if !defined(WIN32) && !defined(DARWIN) +#define __USE_GNU #include +#undef __USE_GNU +#else +#include +#endif #endif #ifdef HAVE_STDDEF_H #include