emit_begin_node(job, n);
ND_shape(n)->fns->codefn(job, n);
+ if (ND_xlabel(n))
+ emit_label(job, EMIT_NLABEL, ND_xlabel(n));
emit_end_node(job);
}
}
if (lp && overlap_label(lp, b))
return TRUE;
+ lp = ED_xlabel(e);
+ if (lp && overlap_label(lp, b))
+ return TRUE;
+
return FALSE;
}
if (flags & GVRENDER_DOES_LABELS) {
if ((lab = ED_label(e)))
obj->label = lab->text;
- obj->taillabel = obj->headlabel = obj->label;
+ obj->taillabel = obj->headlabel = obj->xlabel = obj->label;
+ if ((tlab = ED_xlabel(e)))
+ obj->xlabel = tlab->text;
if ((tlab = ED_tail_label(e)))
obj->taillabel = tlab->text;
if ((hlab = ED_head_label(e)))
obj->explicit_labeltooltip,
obj->labelurl, obj->labeltooltip, obj->labeltarget, obj->id,
((mapbool(late_string(e, E_decorate, "false")) && ED_spl(e)) ? ED_spl(e) : 0));
+ emit_edge_label(job, ED_xlabel(e), EMIT_ELABEL,
+ obj->explicit_labeltooltip,
+ obj->labelurl, obj->labeltooltip, obj->labeltarget, obj->id,
+ ((mapbool(late_string(e, E_decorate, "false")) && ED_spl(e)) ? ED_spl(e) : 0));
emit_edge_label(job, ED_head_label(e), EMIT_HLABEL,
obj->explicit_headtooltip,
obj->headurl, obj->headtooltip, obj->headtarget, obj->id,
N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr);
N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr);
safe_dcl(g, g->proto->e, "pos", "", agedgeattr);
+ if (GD_has_labels(g) & NODE_XLABEL)
+ safe_dcl(g, g->proto->n, "xlp", "", agnodeattr);
if (GD_has_labels(g) & EDGE_LABEL)
safe_dcl(g, g->proto->e, "lp", "", agedgeattr);
+ if (GD_has_labels(g) & EDGE_XLABEL)
+ safe_dcl(g, g->proto->e, "xlp", "", agedgeattr);
if (GD_has_labels(g) & HEAD_LABEL)
safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr);
if (GD_has_labels(g) & TAIL_LABEL)
N_width = safe_dcl(g, AGNODE, "width", "");
N_height = safe_dcl(g, AGNODE, "height", "");
safe_dcl(g, AGEDGE, "pos", "");
+ if (GD_has_labels(g) & NODE_XLABEL)
+ safe_dcl(g, AGNODE, "xlp", "");
if (GD_has_labels(g) & EDGE_LABEL)
safe_dcl(g, AGEDGE, "lp", "");
+ if (GD_has_labels(g) & EDGE_XLABEL)
+ safe_dcl(g, AGEDGE, "xlp", "");
if (GD_has_labels(g) & HEAD_LABEL)
safe_dcl(g, AGEDGE, "head_lp", "");
if (GD_has_labels(g) & TAIL_LABEL)
sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n)));
agxset(n, N_width, buf);
#endif
+ if (ND_xlabel(n)) {
+ ptf = ND_xlabel(n)->pos;
+ sprintf(buf, "%.5g,%.5g", ptf.x, YFDIR(ptf.y));
+ agset(n, "xlp", buf);
+ }
if (strcmp(ND_shape(n)->name, "record") == 0) {
set_record_rects(n, ND_shape_info(n), &xb);
agxbpop(&xb); /* get rid of last space */
sprintf(buf, "%.5g,%.5g", ptf.x, YFDIR(ptf.y));
agset(e, "lp", buf);
}
+ if (ED_xlabel(e)) {
+ ptf = ED_xlabel(e)->pos;
+ sprintf(buf, "%.5g,%.5g", ptf.x, YFDIR(ptf.y));
+ agset(e, "xlp", buf);
+ }
if (ED_head_label(e)) {
ptf = ED_head_label(e)->pos;
sprintf(buf, "%.5g,%.5g", ptf.x, YFDIR(ptf.y));
}
if (ED_label(e))
ED_label(e)->pos = map_point(ED_label(e)->pos);
+ if (ED_xlabel(e))
+ ED_xlabel(e)->pos = map_point(ED_xlabel(e)->pos);
/* vladimir */
if (ED_head_label(e))
ED_head_label(e)->pos = map_point(ED_head_label(e)->pos);
for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
if (Rankdir) gv_nodesize(v, FALSE);
ND_coord(v) = map_point(ND_coord(v));
+ if (ND_xlabel(v))
+ ND_xlabel(v)->pos = map_point(ND_xlabel(v)->pos);
if (State == GVSPLINES)
for (e = agfstout(g, v); e; e = agnxtout(g, e))
map_edge(e);
GD_label(g)->set = TRUE;
}
+static void
+addXLabels (Agraph_t* g)
+{
+}
+
/* dotneato_postprocess:
* Set graph and cluster label positions.
* Add space for root graph label and translate graph accordingly.
* Assumes the boxes of all clusters have been computed.
* When done, the bounding box of g has LL at origin.
*/
-void dotneato_postprocess(Agraph_t * g)
+void gv_postprocess(Agraph_t *g, int addXLabelsOnly)
{
double diff;
pointf dimen = {0., 0.};
+ addXLabels (g);
+ if (addXLabelsOnly)
+ return;
+
Rankdir = GD_rankdir(g);
Flip = GD_flip(g);
if (Flip)
}
}
+void dotneato_postprocess(Agraph_t * g)
+{
+ gv_postprocess (g, 0);
+}
+
/* place_flip_graph_label:
* Put cluster labels recursively in the flip case.
*/
extern void dotneato_args_initialize(GVC_t * gvc, int, char **);
extern void dotneato_usage(int);
extern void dotneato_postprocess(Agraph_t *);
+ extern void gv_postprocess(Agraph_t *, int);
extern void dotneato_set_margins(GVC_t * gvc, Agraph_t *);
extern void dotneato_write(GVC_t * gvc, graph_t *g);
extern void dotneato_write_one(GVC_t * gvc, graph_t *g);
return Tflag;
}
+struct fontinfo {
+ double fontsize;
+ char *fontname;
+ char *fontcolor;
+};
+
void common_init_node_opt(node_t * n, int shape_init_flag)
{
+ struct fontinfo fi;
char *str;
ND_width(n) =
late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH);
#else
str = agxget(n, N_label);
#endif
+ fi.fontsize = late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE);
+ fi.fontname = late_nnstring(n, N_fontname, DEFAULT_FONTNAME);
+ fi.fontcolor = late_nnstring(n, N_fontcolor, DEFAULT_COLOR);
ND_label(n) = make_label((void*)n, str,
((aghtmlstr(str) ? LT_HTML : LT_NONE) | ( (shapeOf(n) == SH_RECORD) ? LT_RECD : LT_NONE)),
- late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE),
- late_nnstring(n, N_fontname, DEFAULT_FONTNAME),
- late_nnstring(n, N_fontcolor, DEFAULT_COLOR));
+ fi.fontsize, fi.fontname, fi.fontcolor);
+#ifndef WITH_CGRAPH
+ if (N_xlabel && (str = agxget(n, N_xlabel->index)) && (str[0])) {
+#else
+ if (N_xlabel && (str = agxget(e, N_xlabel)) && (str[0])) {
+#endif
+ ND_xlabel(n) = make_label((void*)n, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
+ fi.fontsize, fi.fontname, fi.fontcolor);
+ GD_has_labels(agraphof(n)) |= NODE_XLABEL;
+ }
+
ND_showboxes(n) = late_int(n, N_showboxes, 0, 0);
if (shape_init_flag) ND_shape(n)->fns->initfn(n);
}
common_init_node_opt(n,TRUE);
}
-struct fontinfo {
- double fontsize;
- char *fontname;
- char *fontcolor;
-};
-
static void initFontEdgeAttr(edge_t * e, struct fontinfo *fi)
{
fi->fontsize = late_double(e, E_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE);
mapbool(late_string(e, E_label_float, "false"));
}
+#ifndef WITH_CGRAPH
+ if (E_xlabel && (str = agxget(e, E_xlabel->index)) && (str[0])) {
+#else
+ if (E_xlabel && (str = agxget(e, E_xlabel)) && (str[0])) {
+#endif
+ if (!fi.fontname)
+ initFontEdgeAttr(e, &fi);
+ ED_xlabel(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
+ fi.fontsize, fi.fontname, fi.fontcolor);
+ GD_has_labels(sg) |= EDGE_XLABEL;
+ }
+
/* vladimir */
#ifndef WITH_CGRAPH
{
gv_free_splines(e);
free_label(ED_label(e));
+ free_label(ED_xlabel(e));
+ free_label(ED_head_label(e));
+ free_label(ED_tail_label(e));
#ifndef WITH_CGRAPH
memset(&(e->u), 0, sizeof(Agedgeinfo_t));
#else /* WITH_CGRAPH */
if (ND_shape(n))
ND_shape(n)->fns->freefn(n);
free_label(ND_label(n));
+ free_label(ND_xlabel(n));
#ifndef WITH_CGRAPH
memset(&(n->u), 0, sizeof(Agnodeinfo_t));
#else /* WITH_CGRAPH */
typedef enum {ROOTGRAPH_OBJTYPE, CLUSTER_OBJTYPE, NODE_OBJTYPE, EDGE_OBJTYPE} obj_type;
- /* See comment in gvrender_core_dot.c */
+ /* If this enum is changed, the implementation of xbuf and xbufs in
+ * gvrender_core_dot.c will probably need to be changed.
+ */
typedef enum {
EMIT_GDRAW, EMIT_CDRAW, EMIT_TDRAW, EMIT_HDRAW,
- EMIT_GLABEL, EMIT_CLABEL, EMIT_TLABEL, EMIT_HLABEL,
- EMIT_NDRAW, EMIT_EDRAW, EMIT_NLABEL, EMIT_ELABEL,
+ EMIT_GLABEL, EMIT_CLABEL, EMIT_TLABEL, EMIT_HLABEL,
+ EMIT_NDRAW, EMIT_EDRAW, EMIT_NLABEL, EMIT_ELABEL,
} emit_state_t;
typedef struct obj_state_s obj_state_t;
/* fully substituted text strings */
char *label;
+ char *xlabel;
char *taillabel;
char *headlabel;
agerr(AGPREV, "as required by the -n flag\n");
return;
}
- else if (ret == 0)
- dotneato_postprocess(g);
+ else gv_postprocess(g, ret);
} else {
neato_init_graph(g);
layoutMode = neatoMode(g);