From: erg Date: Thu, 15 Mar 2007 22:45:40 +0000 (+0000) Subject: Fix bug 1093; also redo default background in svg output. X-Git-Tag: LAST_LIBGRAPH~32^2~5625 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b47457401ff44e27492439642d103a756ce12622;p=graphviz Fix bug 1093; also redo default background in svg output. --- diff --git a/lib/common/emit.c b/lib/common/emit.c index 739df17f3..df4c177d8 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -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)) { diff --git a/lib/common/htmltable.c b/lib/common/htmltable.c index eb4331737..6ca5da0f0 100644 --- a/lib/common/htmltable.c +++ b/lib/common/htmltable.c @@ -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) diff --git a/lib/common/render.h b/lib/common/render.h index decb21c76..46830f4af 100644 --- a/lib/common/render.h +++ b/lib/common/render.h @@ -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); diff --git a/lib/common/shapes.c b/lib/common/shapes.c index dc1dd1bc1..8308b5121 100644 --- a/lib/common/shapes.c +++ b/lib/common/shapes.c @@ -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; diff --git a/plugin/core/gvrender_core_svg.c b/plugin/core/gvrender_core_svg.c index 1da6c800b..6a86e21e2 100644 --- a/plugin/core/gvrender_core_svg.c +++ b/plugin/core/gvrender_core_svg.c @@ -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 */