/* 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;
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) &&
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) {
}
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 {
continue;
}
objp++;
+ i++;
}
if ((lp = ED_tail_label(ep))) {
if (lp->set) {
}
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 {
continue;
}
objp++;
+ i++;
}
if ((lp = ED_head_label(ep))) {
if (lp->set) {
}
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 {
continue;
}
objp++;
+ i++;
}
if ((lp = ED_xlabel(ep))) {
if (lp->set) {
}
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 {
continue;
}
objp++;
+ i++;
}
}
}
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);