]> granicus.if.org Git - graphviz/commitdiff
Fix bug 1093; also redo default background in svg output.
authorerg <devnull@localhost>
Thu, 15 Mar 2007 22:45:40 +0000 (22:45 +0000)
committererg <devnull@localhost>
Thu, 15 Mar 2007 22:45:40 +0000 (22:45 +0000)
lib/common/emit.c
lib/common/htmltable.c
lib/common/render.h
lib/common/shapes.c
plugin/core/gvrender_core_svg.c

index 739df17f3b84dd9e422a1b6a50b42f385c59dae8..df4c177d89a0e94daa6f2b71b1b2dc2ec549db3a 100644 (file)
@@ -35,7 +35,7 @@
 static char *defaultlinestyle[3] = { "solid\0", "setlinewidth\0001\0", 0 };
 
 /* push empty graphic state for current object */
-static obj_state_t* push_obj_state(GVJ_t *job)
+obj_state_t* push_obj_state(GVJ_t *job)
 {
     obj_state_t *obj, *parent;
 
@@ -62,7 +62,7 @@ static obj_state_t* push_obj_state(GVJ_t *job)
 }
 
 /* pop graphic state of current object */
-static void pop_obj_state(GVJ_t *job)
+void pop_obj_state(GVJ_t *job)
 {
     obj_state_t *obj = job->obj;
 
@@ -85,6 +85,55 @@ static void pop_obj_state(GVJ_t *job)
     free(obj);
 }
 
+void
+initMapData (GVJ_t* job, char* lbl, char* url, char* tooltip, char* target,
+  void* gobj)
+{
+    obj_state_t *obj = job->obj;
+    int flags = job->flags;
+
+    if ((flags & GVRENDER_DOES_LABELS) && lbl)
+        obj->label = lbl;
+    if (obj->url) free (obj->url);
+    if ((flags & GVRENDER_DOES_MAPS) && url && url[0]) {
+        obj->url = strdup_and_subst_obj(url, gobj);
+    }
+    else
+        obj->url = NULL;
+    if (obj->tooltip) free (obj->tooltip);
+    if (flags & GVRENDER_DOES_TOOLTIPS) {
+        if (tooltip && tooltip[0]) {
+            obj->tooltip = strdup_and_subst_obj(tooltip, gobj);
+            obj->explicit_tooltip = TRUE;
+        }
+        else if (obj->label) {
+            obj->tooltip = strdup(obj->label);
+        }
+    }
+    else
+        obj->tooltip = NULL;
+    if (obj->target) free (obj->target);
+    if ((flags & GVRENDER_DOES_TARGETS) && target && target[0]) {
+        obj->target = strdup_and_subst_obj(target, gobj);
+    }
+    else
+        obj->target = NULL;
+}
+
+static void
+initObjMapData (GVJ_t* job, textlabel_t *lab, void* gobj)
+{
+    char* lbl;
+    char* url = agget(gobj, "href");
+    char* tooltip = agget(gobj, "tooltip");
+    char* target = agget(gobj, "target");
+
+    if (lab) lbl = lab->text;
+    else lbl = NULL;
+    if (!url || !*url) url = agget(gobj, "URL");
+    initMapData (job, lbl, url, tooltip, target, gobj);
+}
+
 static void map_point(GVJ_t *job, point P)
 {
     obj_state_t *obj = job->obj;
@@ -978,7 +1027,6 @@ static void emit_begin_node(GVJ_t * job, node_t * n)
 {
     obj_state_t *obj;
     int flags = job->flags;
-    textlabel_t *lab;
     int sides, peripheries, i, j, filled = 0, rect = 0, shape, nump = 0;
     polygon_t *poly = NULL;
     pointf *vertices, ldimen, *p = NULL;
@@ -993,24 +1041,7 @@ static void emit_begin_node(GVJ_t * job, node_t * n)
     if (flags & GVRENDER_DOES_Z) {
         obj->z = late_double(n, N_z, 0.0, -MAXFLOAT);
     }
-    if ((flags & GVRENDER_DOES_LABELS) && ((lab = ND_label(n))))
-        obj->label = lab->text;
-    if ((flags & GVRENDER_DOES_MAPS)
-        && (((s = agget(n, "href")) && s[0]) || ((s = agget(n, "URL")) && s[0]))) {
-        obj->url = strdup_and_subst_obj(s, (void*)n);
-    }
-    if (flags & GVRENDER_DOES_TOOLTIPS) {
-        if ((s = agget(n, "tooltip")) && s[0]) {
-            obj->tooltip = strdup_and_subst_obj(s, (void*)n);
-            obj->explicit_tooltip = TRUE;
-        }
-        else {
-            obj->tooltip = strdup(ND_label(n)->text);
-        }
-    }
-    if ((flags & GVRENDER_DOES_TARGETS) && ((s = agget(n, "target")) && s[0])) {
-        obj->target = strdup_and_subst_obj(s, (void*)n);
-    }
+    initObjMapData (job, ND_label(n), n);
     if ((flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS))
            && (obj->url || obj->explicit_tooltip)) {
 
@@ -2016,32 +2047,14 @@ static void emit_view(GVJ_t * job, graph_t * g, int flags)
 
 static void emit_begin_graph(GVJ_t * job, graph_t * g)
 {
-    int flags = job->flags;
     obj_state_t *obj;
-    char *s;
 
     obj = push_obj_state(job);
     obj->type = ROOTGRAPH_OBJTYPE;
     obj->u.g = g;
     obj->emit_state = EMIT_GDRAW;
 
-    if ((flags & GVRENDER_DOES_MAPS)
-        && (((s = agget(g, "href")) && s[0])
-            || ((s = agget(g, "URL")) && s[0]))) {
-        obj->url = strdup_and_subst_obj(s, (void*)g);
-    }
-    if (flags & GVRENDER_DOES_TOOLTIPS) {
-        if ((s = agget(g, "tooltip")) && s[0]) {
-            obj->tooltip = strdup_and_subst_obj(s, (void*)g);
-            obj->explicit_tooltip = TRUE;
-        }
-        else if (obj->url && obj->label) {
-            obj->tooltip = strdup(obj->label);
-        }
-    }
-    if ((flags & GVRENDER_DOES_TARGETS) && ((s = agget(g, "target")) && s[0])) {
-        obj->target = strdup_and_subst_obj(s, (void*)g);
-    }
+    initObjMapData (job, GD_label(g), g);
 
 #ifdef WITH_CODEGENS
     Obj = NONE;
@@ -2106,7 +2119,7 @@ void emit_graph(GVJ_t * job, graph_t * g)
                obj->label = lab->text;
                /* If EMIT_CLUSTERS_LAST is set, we assume any URL or tooltip
                 * attached to the root graph is emitted either in begin_page
-                * or end_page.
+                * or end_page of renderer.
                 */
             if (!(flags & EMIT_CLUSTERS_LAST) && 
                   (obj->url || obj->explicit_tooltip)) {
@@ -2202,34 +2215,13 @@ static char **checkClusterStyle(graph_t* sg, int *flagp)
 static void emit_begin_cluster(GVJ_t * job, Agraph_t * sg)
 {
     obj_state_t *obj;
-    int flags = job->flags;
-    textlabel_t *lab;
-    char *s;
 
     obj = push_obj_state(job);
     obj->type = CLUSTER_OBJTYPE;
     obj->u.sg = sg;
     obj->emit_state = EMIT_CDRAW;
 
-    if ((flags & GVRENDER_DOES_LABELS) && ((lab = GD_label(sg))))
-        obj->label = lab->text;
-
-    if ((flags & GVRENDER_DOES_MAPS)
-        && (((s = agget(sg, "href")) && s[0]) || ((s = agget(sg, "URL")) && s[0])))
-        obj->url = strdup_and_subst_obj(s, (void*)sg);
-
-    if ((flags & GVRENDER_DOES_TARGETS) && ((s = agget(sg, "target")) && s[0]))
-        obj->target = strdup_and_subst_obj(s, (void*)sg);
-
-    if (flags & GVRENDER_DOES_TOOLTIPS) {
-        if ((s = agget(sg, "tooltip")) && s[0]) {
-            obj->tooltip = strdup_and_subst_obj(s, (void*)sg);
-            obj->explicit_tooltip = TRUE;
-        }
-        else if (obj->label) {
-            obj->tooltip = strdup(obj->label);
-        }
-    }
+    initObjMapData (job, GD_label(sg), sg);
 
 #ifdef WITH_CODEGENS
     Obj = CLST;
@@ -2256,6 +2248,8 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
     node_t *n;
     edge_t *e;
     obj_state_t *obj;
+    textlabel_t *lab;
+    int doAnchor, inAnchor;
 
     for (c = 1; c <= GD_n_cluster(g); c++) {
        sg = GD_clust(g)[c];
@@ -2266,12 +2260,15 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
            emit_clusters(job, sg, flags);
        emit_begin_cluster(job, sg);
        obj = job->obj;
+       doAnchor = (obj->url || obj->explicit_tooltip);
        setColorScheme (agget (sg, "colorscheme"));
        gvrender_begin_context(job);
-       if (obj->url || obj->explicit_tooltip) {
+       if (doAnchor && !(flags & EMIT_CLUSTERS_LAST)) {
+           inAnchor = 1;
            emit_map_rect(job, GD_bb(sg).LL, GD_bb(sg).UR);
            gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
        }
+       else inAnchor = 0;
        filled = FALSE;
        istyle = 0;
        if ((style = checkClusterStyle(sg, &istyle))) {
@@ -2307,7 +2304,7 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
                fillcolor = pencolor = color;
            /* bgcolor is supported for backward compatability */
            else if (((color = agget(sg, "bgcolor")) != 0) && color[0]) {
-               fillcolor = pencolor = color;
+               fillcolor = color;
                filled = TRUE;
             }
            if (((color = agget(sg, "fillcolor")) != 0) && color[0])
@@ -2338,10 +2335,20 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
                gvrender_box(job, BF, filled);
            }
        }
-       if (obj->url || obj->explicit_tooltip)
+       if ((lab = GD_label(sg))) {
+           if (lab->html && inAnchor) {
+               gvrender_end_anchor(job);
+               inAnchor = 0;
+           }
+           emit_label(job, EMIT_CLABEL, lab);
+       }
+       if (doAnchor && (flags & EMIT_CLUSTERS_LAST)) {
+           inAnchor = 1;
+           emit_map_rect(job, GD_bb(sg).LL, GD_bb(sg).UR);
+           gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
+       }
+       if (doAnchor)
            gvrender_end_anchor(job);
-       if (GD_label(sg))
-           emit_label(job, EMIT_CLABEL, GD_label(sg));
 
        if (flags & EMIT_PREORDER) {
            for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
index eb43317379ce3a1b6788a3036015c3f0eb4a8de3..6ca5da0f033fcb1ce5013d79a0cd6200811e98fe 100644 (file)
@@ -268,14 +268,28 @@ static void doFill(GVJ_t * job, char *color, box B)
     gvrender_box(job, BF, 1);
 }
 
-static void doAnchorStart(GVJ_t * job, htmldata_t * data)
+/* initAnchor:
+ * Initialize fields in job->obj pertaining to anchors.
+ * In particular, this also sets the output rectangle.
+ * If there is somethine to do, it starts the anchor and returns 1
+ * Otherwise, it returns 0.
+ *
+ * FIX: Should we provide a tooltip if none is set, as is done
+ * for nodes, edges, etc. ?
+ */
+static int
+initAnchor (GVJ_t* job, htmldata_t* data, box pts)
 {
-    gvrender_begin_anchor(job, data->href, data->title, data->target);
-}
+    obj_state_t *obj = job->obj;
 
-static void doAnchorEnd(GVJ_t * job)
-{
-    gvrender_end_anchor(job);
+    initMapData (job, NULL, data->href, data->title, data->target, obj->u.g);
+
+    if (obj->url || obj->tooltip) {
+       emit_map_rect(job, pts.LL, pts.UR);
+       gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
+       return 1;
+    }
+    else return 0;
 }
 
 /* forward declaration */
@@ -288,6 +302,7 @@ emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env)
     point p = env->p;
     htmlcell_t **cells = tbl->u.n.cells;
     htmlfont_t savef;
+    int inAnchor, doAnchor = (tbl->data.href || tbl->data.target);
 
     if (tbl->font)
        pushFontInfo(env, tbl->font, &savef);
@@ -297,26 +312,30 @@ emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env)
     pts.LL.y += p.y;
     pts.UR.y += p.y;
 
-    /* gvrender_begin_context(job); */
-
-    if (tbl->data.href)
-       doAnchorStart(job, &tbl->data);
+    if (doAnchor && !(job->flags & EMIT_CLUSTERS_LAST))
+       inAnchor = initAnchor(job, &tbl->data, pts);
+    else
+       inAnchor = 0;
 
     if (tbl->data.bgcolor)
        doFill(job, tbl->data.bgcolor, pts);
 
+    if (tbl->data.border)
+       doBorder(job, tbl->data.pencolor, tbl->data.border, pts);
+
+    if (inAnchor)
+       gvrender_end_anchor(job);
+
     while (*cells) {
        emit_html_cell(job, *cells, env);
        cells++;
     }
 
-    if (tbl->data.border)
-       doBorder(job, tbl->data.pencolor, tbl->data.border, pts);
-
-    if (tbl->data.href)
-       doAnchorEnd(job);
+    if (doAnchor && (job->flags & EMIT_CLUSTERS_LAST)) {
+       if (initAnchor(job, &tbl->data, pts))
+           gvrender_end_anchor(job);
+    }
 
-    /* gvrender_end_context(job); */
     if (tbl->font)
        popFontInfo(env, &savef);
 }
@@ -347,21 +366,27 @@ emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env)
 {
     box pts = cp->data.box;
     point p = env->p;
+    int inAnchor, doAnchor = (cp->data.href || cp->data.target);
 
     pts.LL.x += p.x;
     pts.UR.x += p.x;
     pts.LL.y += p.y;
     pts.UR.y += p.y;
 
-    /* gvrender_begin_context(); */
+    if (doAnchor && !(job->flags & EMIT_CLUSTERS_LAST))
+       inAnchor = initAnchor(job, &cp->data, pts);
+    else
+       inAnchor = 0;
 
-    if (cp->data.href) {
-       emit_map_rect(job, pts.LL, pts.UR);
-       doAnchorStart(job, &cp->data);
+    if (cp->data.bgcolor) {
+       doFill(job, cp->data.bgcolor, pts);
     }
 
-    if (cp->data.bgcolor)
-       doFill(job, cp->data.bgcolor, pts);
+    if (cp->data.border)
+       doBorder(job, cp->data.pencolor, cp->data.border, pts);
+
+    if (inAnchor)
+       gvrender_end_anchor(job);
 
     if (cp->child.kind == HTML_TBL)
        emit_html_tbl(job, cp->child.u.tbl, env);
@@ -370,13 +395,52 @@ emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env)
     else
        emit_html_txt(job, cp->child.u.txt, env);
 
-    if (cp->data.border)
-       doBorder(job, cp->data.pencolor, cp->data.border, pts);
-
-    if (cp->data.href)
-       doAnchorEnd(job);
+    if (doAnchor && (job->flags & EMIT_CLUSTERS_LAST)) {
+       if (initAnchor(job, &cp->data, pts))
+           gvrender_end_anchor(job);
+    }
+}
 
-    /* gvrender_end_context(); */
+/* allocObj:
+ * Push new obj on stack to be used in common by all 
+ * html elements with anchors.
+ * This inherits the type, emit_state, and object of the
+ * parent.
+ */
+static void
+allocObj (GVJ_t * job)
+{
+    obj_state_t *obj;
+
+    obj = push_obj_state(job);
+    obj->type = obj->parent->type;
+    obj->emit_state = obj->parent->emit_state;
+    switch (obj->type) {
+    case NODE_OBJTYPE :
+       obj->u.n = obj->parent->u.n;
+#ifdef WITH_CODEGENS
+       Obj = NODE;
+#endif
+       break;
+    case ROOTGRAPH_OBJTYPE :
+       obj->u.g = obj->parent->u.g;
+#ifdef WITH_CODEGENS
+       Obj = NONE;
+#endif
+       break;
+    case CLUSTER_OBJTYPE :
+       obj->u.sg = obj->parent->u.sg;
+#ifdef WITH_CODEGENS
+       Obj = CLST;
+#endif
+       break;
+    case EDGE_OBJTYPE :
+       obj->u.e = obj->parent->u.e;
+#ifdef WITH_CODEGENS
+       Obj = EDGE;
+#endif
+       break;
+    }
 }
 
 /* emit_html_label:
@@ -386,6 +450,7 @@ emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp)
 {
     htmlenv_t env;
 
+    allocObj (job);
     env.p = tp->p;
     env.finfo.color = tp->fontcolor;
     env.finfo.name = tp->fontname;
@@ -406,6 +471,7 @@ emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp)
     } else {
        emit_html_txt(job, lp->u.txt, &env);
     }
+    pop_obj_state(job);
 }
 
 void free_html_font(htmlfont_t * fp)
index decb21c76cc04d77e30ecf5c4f0612f29db12fec..46830f4af34db8e8e0133b00f8594e1bfc3e709d 100644 (file)
@@ -115,6 +115,7 @@ extern "C" {
     extern void global_def(char *,
                           Agsym_t * (*fun) (Agraph_t *, char *, char *));
     extern int gvRenderJobs (GVC_t * gvc, graph_t * g);
+    extern void initMapData (GVJ_t*, char*, char*, char*, char*, void*);
     extern boolean isPolygon(node_t *);
     extern char *strdup_and_subst_obj(char *str, void *obj);
     extern char *xml_string(char *s);
@@ -128,6 +129,8 @@ extern "C" {
     extern void place_graph_label(Agraph_t *);
     extern void place_portlabel(edge_t * e, boolean head_p);
     extern char *ps_string(char *s, int);
+    extern void pop_obj_state(GVJ_t *job);
+    extern obj_state_t* push_obj_state(GVJ_t *job);
     extern int rank(graph_t * g, int balance, int maxiter);
     extern void round_corners(GVJ_t*, char*, char*, pointf*, int, int);
     extern void routesplinesinit(void);
index dc1dd1bc1dbd460f90743bd8ffef9c1f16248f18..8308b512107e33ae93a84793fcc3e2f4f8088b69 100644 (file)
@@ -1194,8 +1194,9 @@ static void poly_gencode(GVJ_t * job, node_t * n)
     static int A_size;
     boolean filled;
     char *color, *name;
+    int doMap = (obj->url || obj->explicit_tooltip);
 
-    if (obj->url || obj->explicit_tooltip)
+    if (doMap && !(job->flags & EMIT_CLUSTERS_LAST))
        gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
 
     poly = (polygon_t *) ND_shape_info(n);
@@ -1312,14 +1313,21 @@ static void poly_gencode(GVJ_t * job, node_t * n)
     }
 
     if (ND_label(n)->html) {
-        if (obj->url || obj->explicit_tooltip)
+       if (doMap && !(job->flags & EMIT_CLUSTERS_LAST))
             gvrender_end_anchor(job);
         emit_label(job, EMIT_NLABEL, ND_label(n));
+       if (doMap && (job->flags & EMIT_CLUSTERS_LAST)) {
+           gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
+            gvrender_end_anchor(job);
+       }
     }
     else {
         emit_label(job, EMIT_NLABEL, ND_label(n));
-        if (obj->url || obj->explicit_tooltip)
+        if (doMap) {
+           if (job->flags & EMIT_CLUSTERS_LAST)
+               gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
             gvrender_end_anchor(job);
+       }
     }
 
 }
@@ -1891,6 +1899,7 @@ static void record_gencode(GVJ_t * job, node_t * n)
     pointf AF[4];
     int style;
     field_t *f;
+    int doMap = (obj->url || obj->explicit_tooltip);
 
     f = (field_t *) ND_shape_info(n);
     B2BF(f->b, BF);
@@ -1899,7 +1908,7 @@ static void record_gencode(GVJ_t * job, node_t * n)
     BF.UR.x += (double)(ND_coord_i(n).x);
     BF.UR.y += (double)(ND_coord_i(n).y);
     
-    if (obj->url || obj->explicit_tooltip)
+    if (doMap && !(job->flags & EMIT_CLUSTERS_LAST))
         gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
     style = stylenode(job, n);
     pencolor(job, n);
@@ -1919,10 +1928,14 @@ static void record_gencode(GVJ_t * job, node_t * n)
     else
        gvrender_box(job, BF, style & FILLED);
 
-    if (obj->url || obj->explicit_tooltip)
+    if (doMap && !(job->flags & EMIT_CLUSTERS_LAST))
         gvrender_end_anchor(job);
 
     gen_fields(job, n, f);
+    if (doMap && (job->flags & EMIT_CLUSTERS_LAST)) {
+        gvrender_begin_anchor(job, obj->url, obj->tooltip, obj->target);
+        gvrender_end_anchor(job);
+    }
 }
 
 static shape_desc **UserShape;
index 1da6c800bb843670b4e0e1a5f183ddbca5055533..6a86e21e2c9f3a754418e97f2b9177b916c5391b 100644 (file)
@@ -478,7 +478,6 @@ gvrender_features_t svg_features = {
         | GVRENDER_DOES_TRANSFORM
        | GVRENDER_DOES_LABELS
        | GVRENDER_DOES_MAPS
-       | GVRENDER_NO_BG
        | GVRENDER_DOES_TARGETS
        | GVRENDER_DOES_TOOLTIPS, /* flags */
     DEFAULT_EMBED_MARGIN,      /* default margin - points */