From: erg Date: Thu, 15 Oct 2009 17:28:19 +0000 (+0000) Subject: Add support for external labels X-Git-Tag: LAST_LIBGRAPH~32^2~1651 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ba088f43ab1973d774593b53d4644ad8ae9cf4b6;p=graphviz Add support for external labels --- diff --git a/lib/common/emit.c b/lib/common/emit.c index c4e8371ae..155fbdd8d 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -1348,6 +1348,8 @@ static void emit_node(GVJ_t * job, node_t * n) 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); } } @@ -1635,6 +1637,10 @@ static boolean edge_in_box(edge_t *e, boxf b) if (lp && overlap_label(lp, b)) return TRUE; + lp = ED_xlabel(e); + if (lp && overlap_label(lp, b)) + return TRUE; + return FALSE; } @@ -1683,7 +1689,9 @@ static void emit_begin_edge(GVJ_t * job, edge_t * e, char** styles) 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))) @@ -1943,6 +1951,10 @@ static void emit_end_edge(GVJ_t * job) 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, diff --git a/lib/common/output.c b/lib/common/output.c index 4d78ceaca..38937566d 100644 --- a/lib/common/output.c +++ b/lib/common/output.c @@ -272,8 +272,12 @@ void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) 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) @@ -293,8 +297,12 @@ void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) 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) @@ -326,6 +334,11 @@ void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) 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 */ @@ -402,6 +415,11 @@ void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) 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)); diff --git a/lib/common/postproc.c b/lib/common/postproc.c index 9d7046d70..4cc70f2f9 100644 --- a/lib/common/postproc.c +++ b/lib/common/postproc.c @@ -111,6 +111,8 @@ static void map_edge(edge_t * e) } 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); @@ -154,6 +156,8 @@ static void translate_drawing(graph_t * g) 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); @@ -189,6 +193,11 @@ static void place_root_label(graph_t * g, pointf d) 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. @@ -196,11 +205,15 @@ static void place_root_label(graph_t * g, pointf d) * 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) @@ -274,6 +287,11 @@ void dotneato_postprocess(Agraph_t * g) } } +void dotneato_postprocess(Agraph_t * g) +{ + gv_postprocess (g, 0); +} + /* place_flip_graph_label: * Put cluster labels recursively in the flip case. */ diff --git a/lib/common/render.h b/lib/common/render.h index 7c60b9b16..61bbdf29e 100644 --- a/lib/common/render.h +++ b/lib/common/render.h @@ -98,6 +98,7 @@ extern "C" { 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); diff --git a/lib/common/utils.c b/lib/common/utils.c index 52b68ca93..b49f581c0 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -586,8 +586,15 @@ int test_toggle() 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); @@ -600,11 +607,22 @@ void common_init_node_opt(node_t * n, int shape_init_flag) #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); } @@ -613,12 +631,6 @@ void common_init_node(node_t * 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); @@ -709,6 +721,18 @@ int common_init_edge(edge_t * e) 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 @@ -1815,6 +1839,9 @@ void gv_cleanup_edge(edge_t * e) { 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 */ @@ -1829,6 +1856,7 @@ void gv_cleanup_node(node_t * n) 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 */ diff --git a/lib/gvc/gvcjob.h b/lib/gvc/gvcjob.h index 4e2d4a80e..234382507 100644 --- a/lib/gvc/gvcjob.h +++ b/lib/gvc/gvcjob.h @@ -179,11 +179,13 @@ extern "C" { 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; @@ -211,6 +213,7 @@ extern "C" { /* fully substituted text strings */ char *label; + char *xlabel; char *taillabel; char *headlabel; diff --git a/lib/neatogen/neatoinit.c b/lib/neatogen/neatoinit.c index eb9528828..ca0a3dd1f 100644 --- a/lib/neatogen/neatoinit.c +++ b/lib/neatogen/neatoinit.c @@ -1494,8 +1494,7 @@ void neato_layout(Agraph_t * g) 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);