]> granicus.if.org Git - graphviz/commitdiff
Add support for external labels
authorerg <devnull@localhost>
Thu, 15 Oct 2009 17:28:19 +0000 (17:28 +0000)
committererg <devnull@localhost>
Thu, 15 Oct 2009 17:28:19 +0000 (17:28 +0000)
lib/common/emit.c
lib/common/output.c
lib/common/postproc.c
lib/common/render.h
lib/common/utils.c
lib/gvc/gvcjob.h
lib/neatogen/neatoinit.c

index c4e8371aec1704fbd4210952e3832696f721ae84..155fbdd8da9efe523f4e93a9bd4a89e2b70edaad 100644 (file)
@@ -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,
index 4d78ceacabc362b0d1518bd956fd74e428313200..38937566d4b3f80f8acb253fca7460dbefb3a4e2 100644 (file)
@@ -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));
index 9d7046d707d52439816c7249ae3e03b8b0c663a5..4cc70f2f96e645e918cdb1881d97ddb5543e7e87 100644 (file)
@@ -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.
  */
index 7c60b9b165036ab6051bde4c89e984d121470c8e..61bbdf29eaef15f534add3b6387ae35a70ff2fa9 100644 (file)
@@ -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);
index 52b68ca93a751410fbffe8d4903584c56932486f..b49f581c03213de28f1e9ca1e87f21f14e2eca0b 100644 (file)
@@ -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 */
index 4e2d4a80ed18d93149002d8e649fb7a034a67603..234382507577baa397f96ae2320e8a0a5d4ef6b8 100644 (file)
@@ -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; 
 
index eb9528828bb0b274f703e93fd050e4b2e2beddbf..ca0a3dd1f6a5aa30f0aec911e20c09ed3770c47e 100644 (file)
@@ -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);