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;
}
/* 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;
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;
{
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;
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)) {
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;
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)) {
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;
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];
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))) {
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])
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)) {
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 */
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);
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);
}
{
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);
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:
{
htmlenv_t env;
+ allocObj (job);
env.p = tp->p;
env.finfo.color = tp->fontcolor;
env.finfo.name = tp->fontname;
} else {
emit_html_txt(job, lp->u.txt, &env);
}
+ pop_obj_state(job);
}
void free_html_font(htmlfont_t * fp)
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);
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);
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);
}
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);
+ }
}
}
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);
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);
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;
| 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 */