static void emit_node(GVJ_t * job, node_t * n)
{
GVC_t *gvc = job->gvc;
- char *s, *url = NULL, *tooltip = NULL, *target = NULL;
- int oldstate, explicit_tooltip = 0;
+ char *s;
+ int oldstate;
if (ND_shape(n) == NULL)
return;
gvrender_comment(job, s);
gvrender_begin_node(job, n);
- if (((s = agget(n, "href")) && s[0]) || ((s = agget(n, "URL")) && s[0]))
- url = strdup_and_subst_node(s, n);
-
- if ((s = agget(n, "tooltip")) && s[0]) {
- tooltip = strdup_and_subst_node(s, n);
- explicit_tooltip++;
- } else {
- tooltip = strdup_and_subst_node(ND_label(n)->text, n);
- }
-
- if ((s = agget(n, "target")) && s[0])
- target = strdup_and_subst_node(s, n);
-
- if (url || explicit_tooltip)
- gvrender_begin_anchor(job, url, tooltip, target);
-
setColorScheme (agget (n, "colorscheme"));
gvrender_begin_context(job);
ND_shape(n)->fns->codefn(job, n);
ND_state(n) = gvc->common.viewNum;
gvrender_end_context(job);
-
- if (url || explicit_tooltip)
- gvrender_end_anchor(job);
- free(url);
- free(tooltip);
- free(target);
gvrender_end_node(job);
}
gvc->emit_state = oldstate;
static void emit_edge(GVJ_t * job, edge_t * e)
{
- char *s, *url = NULL, *label = NULL, *tooltip = NULL, *target = NULL;
- textlabel_t *lab = NULL;
- int oldstate, explicit_tooltip=0;
+ char *s;
+ int oldstate;
if (! edge_in_box(e, job->pageBoxClip) || ! edge_in_layer(job, e->head->graph, e))
return;
gvrender_comment(job, s);
gvrender_begin_edge(job, e);
- if (((s = agget(e, "href")) && s[0]) || ((s = agget(e, "URL")) && s[0]))
- url = strdup_and_subst_edge(s, e);
- if ((lab = ED_label(e)))
- label = lab->text;
- if ((s = agget(e, "tooltip")) && s[0]) {
- tooltip = strdup_and_subst_edge(s, e);
- explicit_tooltip++;
- } else if (label) {
- tooltip = strdup_and_subst_edge(label, e);
- }
- if ((s = agget(e, "target")) && s[0])
- target = strdup_and_subst_edge(s, e);
- if (url || explicit_tooltip)
- gvrender_begin_anchor(job, url, tooltip, target);
emit_edge_graphics (job, e);
- if (url || explicit_tooltip)
- gvrender_end_anchor(job);
- free(url);
- free(tooltip);
- free(target);
gvrender_end_edge(job);
job->gvc->emit_state = oldstate;
}
GVC_t * gvc = job->gvc;
node_t *n;
edge_t *e;
- char *s, *url = NULL, *tooltip = NULL, *target = NULL;
- int explicit_tooltip = 0;
gvc->common.viewNum++;
- if (((s = agget(g, "href")) && s[0]) || ((s = agget(g, "URL")) && s[0]))
- url = strdup_and_subst_graph(s, g);
- if ((s = agget(g, "target")) && s[0])
- target = strdup_and_subst_graph(s, g);
- if ((s = agget(g, "tooltip")) && s[0]) {
- tooltip = strdup_and_subst_graph(s, g);
- explicit_tooltip++;
- } else if (GD_label(g)) {
- tooltip = strdup_and_subst_graph(GD_label(g)->text, g);
- }
- if (url || explicit_tooltip)
- gvrender_begin_anchor(job, url, tooltip, target);
if (GD_label(g))
emit_label(job, EMIT_GLABEL, GD_label(g), (void *) g);
/* when drawing, lay clusters down before nodes and edges */
/* when mapping, detect events on clusters after nodes and edges */
if (flags & EMIT_CLUSTERS_LAST)
emit_clusters(job, g, flags);
- if (url || explicit_tooltip)
- gvrender_end_anchor(job);
- free(url);
- free(tooltip);
- free(target);
gvrender_end_page(job);
}
char *color, *fillcolor, *pencolor, **style;
node_t *n;
edge_t *e;
- char *s, *url, *tooltip, *target;
- int oldstate, explicit_tooltip;
+ int oldstate;
oldstate = job->gvc->emit_state;
job->gvc->emit_state = EMIT_CDRAW;
if (flags & EMIT_CLUSTERS_LAST)
emit_clusters(job, sg, flags);
gvrender_begin_cluster(job, sg);
-
- url = tooltip = target = NULL;
- explicit_tooltip = 0;
-
- if (((s = agget(sg, "href")) && s[0]) || ((s = agget(sg, "URL")) && s[0]))
- url = strdup_and_subst_graph(s, sg);
-
- if ((s = agget(sg, "target")) && s[0])
- target = strdup_and_subst_graph(s, sg);
- if ((s = agget(sg, "tooltip")) && s[0]) {
- tooltip = strdup_and_subst_graph(s, sg);
- explicit_tooltip++;
- } else if (GD_label(sg)) {
- tooltip = strdup_and_subst_graph(GD_label(sg)->text, sg);
- }
- if (url || explicit_tooltip)
- gvrender_begin_anchor(job, url, tooltip, target);
-
setColorScheme (agget (sg, "colorscheme"));
gvrender_begin_context(job);
filled = FALSE;
emit_edge(job, e);
}
}
-
gvrender_end_context(job);
- if (url || explicit_tooltip)
- gvrender_end_anchor(job);
-
- free(url);
- free(tooltip);
- free(target);
gvrender_end_cluster(job, g);
/* when drawing, lay down clusters before sub_clusters */
if (!(flags & EMIT_CLUSTERS_LAST))
}
#if ! NEWANCHORS
-static void mapOutput (char* shapename, point* pp, int nump,
+static void mapOutput (map_shape_t map_shape, point* pp, int nump,
char* url, char *target, char *label, char *tooltip)
{
int i;
if (Output_lang == IMAP && url && url[0]) {
- fprintf(Output_file, "%s %s ", shapename, url);
- if (strcmp(shapename, "circle") == 0)
- fprintf(Output_file, "%d,%d %d,%d",
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ fprintf(Output_file, "rectangle %s %d %d %d %d\n", url,
+ pp[0].x, pp[0].y, pp[1].x, pp[1].y);
+ break;
+ case MAP_CIRCLE:
+ fprintf(Output_file, "circle %s %d %d %d %d\n", url,
pp[0].x, pp[0].y, (pp[1].x+pp[0].x), pp[0].y);
- else {
+ break;
+ case MAP_POLYGON:
+ fprintf(Output_file, "poly %s", url);
for (i = 0; i < nump; i++)
- fprintf(Output_file, "%d,%d ", pp[i].x, pp[i].y);
+ fprintf(Output_file, " %d,%d", pp[i].x, pp[i].y);
+ fprintf(Output_file, "\n");
+ break;
+ default:
+ assert(0);
+ break;
}
- fprintf(Output_file, "\n");
} else if (Output_lang == ISMAP && url && url[0]) {
- fprintf(Output_file, "rectangle (%d,%d) (%d,%d) %s %s\n",
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ fprintf(Output_file, "rectangle (%d,%d) (%d,%d) %s %s\n",
pp[0].x, pp[0].y, pp[1].x, pp[1].y, url, label);
+ break;
+ default:
+ assert(0);
+ break;
+ }
} else if (Output_lang == CMAP || Output_lang == CMAPX) {
- fprintf(Output_file, "<area shape=\"%s\"", shapename);
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ fprintf(Output_file, "<area shape=\"rect\"");
+ break;
+ case MAP_CIRCLE:
+ fprintf(Output_file, "<area shape=\"circle\"");
+ break;
+ case MAP_POLYGON:
+ fprintf(Output_file, "<area shape=\"poly\"");
+ break;
+ default:
+ assert(0);
+ break;
+ }
if (url && url[0])
fprintf(Output_file, " href=\"%s\"", xml_string(url));
if (target && target[0])
fprintf(Output_file, " alt=\"\"");
fprintf(Output_file, " coords=\"");
- if (strcmp(shapename, "circle") == 0)
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ fprintf(Output_file, "%d,%d,%d,%d\"", pp[0].x, pp[0].y, pp[1].x, pp[1].y);
+ break;
+ case MAP_CIRCLE:
fprintf(Output_file, "%d,%d,%d\"", pp[0].x, pp[0].y, pp[1].x);
- else {
- for (i = 0; i < nump; i++)
- fprintf(Output_file, "%d,%d ", pp[i].x, pp[i].y);
+ break;
+ case MAP_POLYGON:
+ fprintf(Output_file, "%d,%d", pp[0].x, pp[0].y);
+ for (i = 1; i < nump; i++)
+ fprintf(Output_file, " %d,%d", pp[i].x, pp[i].y);
fprintf(Output_file, "\"");
+ break;
+ default:
+ break;
}
-
if (Output_lang == CMAPX)
fprintf(Output_file, " /");
fprintf(Output_file, ">\n");
int sides, peri, nump, i, j, filled = 0, rect = 0, nshape;
pointf *ppf, *vertices, ldimen;
point *pp, coord;
- char *shapename;
+ map_shape_t map_shape;
polygon_t *poly = NULL;
/* checking shape of node */
* when polygon has no peripheries and node is not filled
*/
if (poly->peripheries == 0 && !filled) {
- shapename = "rect";
+ map_shape = MAP_RECTANGLE;
nump = 2;
ppf = N_NEW(nump, pointf);
pp = N_NEW(nump, point);
else if (poly->sides < 3 && poly->skew == 0.0
&& poly->distortion == 0.0) {
if (poly->regular) {
- shapename = "circle"; /* circle */
+ map_shape = MAP_CIRCLE;
nump = 2; /* center of circle and radius */
ppf = N_NEW(nump, pointf);
pp = N_NEW(nump, point);
}
else { /* ellipse is treated as polygon */
double a, b;
- shapename = "poly"; /* ellipse */
+ map_shape = MAP_POLYGON;
a = vertices[peri - 1].x;
b = vertices[peri - 1].y;
nump = sample;
/* all other polygonal shape */
} else {
int offset = (peri - 1)*(poly->sides);
- shapename = "poly";
+ map_shape = MAP_POLYGON;
/* distorted or skewed ellipses and circles are polygons with 120
* sides. For mapping we convert them into polygon with sample sides
*/
* when requested output format is neither imap nor cmapx and for all
* node shapes other than polygon ( except regular rectangle polygon )
*/
- shapename = "rect";
+ map_shape = MAP_RECTANGLE;
nump = 2;
ppf = N_NEW(nump, pointf);
pp = N_NEW(nump, point);
}
#if ! NEWANCHORS
- mapOutput (shapename, pp, nump, url, target, label, tooltip);
+ mapOutput (map_shape, pp, nump, url, target, label, tooltip);
#endif
free(ppf);
free(pp);
pp[0].y = t;
}
#if ! NEWANCHORS
- mapOutput ("rect", pp, 2, url, target, label, tooltip);
+ mapOutput (MAP_RECTANGLE, pp, 2, url, target, label, tooltip);
#endif
}
rp[last-i].x = ROUND(ppf.x);
rp[last-i].y = ROUND(ppf.y);
}
- mapOutput ("poly", rp, last+1, url, target, NULL, tooltip);
+ mapOutput (MAP_POLYGON, rp, last+1, url, target, NULL, tooltip);
#ifdef DEBUG
psmapOutput (rp, last+1);
#endif
#define GVRENDER_DOES_TRANSFORM (1<<11)
#define GVRENDER_DOES_LABELS (1<<12)
#define GVRENDER_DOES_MAPS (1<<13)
-#define GVRENDER_DOES_MAP_RECT (1<<14)
-#define GVRENDER_DOES_MAP_ELLIPSE (1<<15)
-#define GVRENDER_DOES_MAP_POLY (1<<16)
-#define GVRENDER_DOES_MAP_BSPLINE (1<<17)
-#define GVRENDER_DOES_TOOLTIPS (1<<18)
-#define GVRENDER_DOES_TARGETS (1<<19)
-#define GVRENDER_DOES_Z (1<<20)
+#define GVRENDER_DOES_MAP_RECTANGLE (1<<14)
+#define GVRENDER_DOES_MAP_CIRCLE (1<<15)
+#define GVRENDER_DOES_MAP_POLYGON (1<<16)
+#define GVRENDER_DOES_MAP_ELLIPSE (1<<17)
+#define GVRENDER_DOES_MAP_BSPLINE (1<<18)
+#define GVRENDER_DOES_TOOLTIPS (1<<19)
+#define GVRENDER_DOES_TARGETS (1<<20)
+#define GVRENDER_DOES_Z (1<<21)
typedef struct {
int flags;
gvevent_key_callback_t callback;
} gvevent_key_binding_t;
+ typedef enum {MAP_RECTANGLE, MAP_CIRCLE, MAP_POLYGON, } map_shape_t;
+
typedef struct obj_state_s obj_state_t;
struct obj_state_s {
char *tooltip; /* if GVRENDER_DOES_TOOLTIPS */
char *tailtooltip;
char *headtooltip;
+ bool explicit_tooltip;
+ bool explicit_tailtooltip;
+ bool explicit_headtooltip;
char *target; /* if GVRENDER_DOES_TARGETS */
char *tailtarget;
char *headtarget;
/* primary mapped region - node shape, edge label */
- char *url_map_shapename; /* "rect", "poly", "circle" */
+ map_shape_t url_map_shape;
int url_map_n; /* number of points for url map if GVRENDER_DOES_MAPS */
pointf *url_map_p;
return strcmp(*(char **) s1, *(char **) s2);
}
+static void rect2poly(pointf *p)
+{
+ p[3].x = p[2].x = p[1].x;
+ p[2].y = p[1].y;
+ p[3].y = p[0].y;
+ p[1].x = p[0].x;
+}
+
static void gvrender_resolve_color(gvrender_features_t * features,
char *name, gvcolor_t * color)
{
void gvrender_begin_page(GVJ_t * job)
{
gvrender_engine_t *gvre = job->render.engine;
+ obj_state_t *obj = job->obj;
+ int nump = 0, flags = job->flags;
+ pointf *p = NULL;
+
+ if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
+ if (flags & (GVRENDER_DOES_MAP_RECTANGLE | GVRENDER_DOES_MAP_POLYGON)) {
+ if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
+ obj->url_map_shape = MAP_RECTANGLE;
+ nump = 2;
+ }
+ else {
+ obj->url_map_shape = MAP_POLYGON;
+ nump = 4;
+ }
+
+ p = N_NEW(nump, pointf);
+ p[0] = job->pageBox.LL;
+ p[1] = job->pageBox.UR;
+
+ if (! (flags & (GVRENDER_DOES_MAP_RECTANGLE)))
+ rect2poly(p);
+ }
+ if (! (flags & GVRENDER_DOES_TRANSFORM))
+ gvrender_ptf_A(job, p, p, nump);
+ obj->url_map_p = p;
+ obj->url_map_n = nump;
+ }
if (gvre) {
+ if (gvre->begin_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->begin_anchor(job, obj->url, obj->tooltip, obj->target);
if (gvre->begin_page)
gvre->begin_page(job);
}
point offset;
PF2P(job->pageOffset, offset);
+ if (cg && cg->begin_anchor && (obj->url || obj->explicit_tooltip))
+ cg->begin_anchor(obj->url, obj->tooltip, obj->target);
if (cg && cg->begin_page)
cg->begin_page(job->gvc->g, job->pagesArrayElem,
job->zoom, job->rotation, offset);
void gvrender_end_page(GVJ_t * job)
{
gvrender_engine_t *gvre = job->render.engine;
+ obj_state_t *obj = job->obj;
if (gvre) {
if (gvre->end_page)
gvre->end_page(job);
+ if (gvre->end_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->end_anchor(job);
}
#ifdef WITH_CODEGENS
else {
if (cg && cg->end_page)
cg->end_page();
+ if (cg && cg->end_anchor && (obj->url || obj->explicit_tooltip))
+ cg->end_anchor();
}
#endif
}
#endif
}
-static void rect2poly(pointf *p)
-{
- p[3].x = p[2].x = p[1].x;
- p[2].y = p[1].y;
- p[3].y = p[0].y;
- p[1].x = p[0].x;
-}
-
void gvrender_begin_cluster(GVJ_t * job, graph_t * sg)
{
gvrender_engine_t *gvre = job->render.engine;
obj->tooltip = strdup_and_subst_graph(s, sg);
if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
- if (flags & (GVRENDER_DOES_MAP_RECT | GVRENDER_DOES_MAP_POLY)) {
- if (flags & GVRENDER_DOES_MAP_RECT) {
- obj->url_map_shapename = "rect";
+ if (flags & (GVRENDER_DOES_MAP_RECTANGLE | GVRENDER_DOES_MAP_POLYGON)) {
+ if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
+ obj->url_map_shape = MAP_RECTANGLE;
nump = 2;
}
else {
- obj->url_map_shapename = "poly";
+ obj->url_map_shape = MAP_POLYGON;
nump = 4;
}
P2PF(GD_bb(sg).LL, p[0]);
P2PF(GD_bb(sg).UR, p[1]);
- if (! (flags & (GVRENDER_DOES_MAP_RECT)))
+ if (! (flags & (GVRENDER_DOES_MAP_RECTANGLE)))
rect2poly(p);
}
obj->url_map_p = p;
}
if (gvre) {
+ if (gvre->begin_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->begin_anchor(job, obj->url, obj->tooltip, obj->target);
if (gvre->begin_cluster)
gvre->begin_cluster(job);
}
codegen_t *cg = job->codegen;
Obj = CLST;
+ if (cg && cg->begin_anchor && (obj->url || obj->explicit_tooltip))
+ cg->begin_anchor(obj->url, obj->tooltip, obj->target);
if (cg && cg->begin_cluster)
cg->begin_cluster(sg);
}
void gvrender_end_cluster(GVJ_t * job, graph_t *g)
{
gvrender_engine_t *gvre = job->render.engine;
+ obj_state_t *obj = job->obj;
if (gvre) {
if (gvre->end_cluster)
gvre->end_cluster(job);
+ if (gvre->end_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->end_anchor(job);
}
#ifdef WITH_CODEGENS
else {
if (cg && cg->end_cluster)
cg->end_cluster();
+ if (cg && cg->end_anchor && (obj->url || obj->explicit_tooltip))
+ cg->end_anchor();
}
Obj = NONE;
#endif
gvrender_engine_t *gvre = job->render.engine;
obj_state_t *obj;
textlabel_t *lab;
- int flags, sides, peripheries, i, j, filled = 0, rect = 0, shape, sample = 100, nump = 0;
+ int flags, sides, peripheries, i, j, filled = 0, rect = 0, shape, nump = 0;
polygon_t *poly = NULL;
pointf *vertices, ldimen, *p = NULL;
point coord;
&& (((s = agget(n, "href")) && s[0]) || ((s = agget(n, "URL")) && s[0]))) {
obj->url = strdup_and_subst_node(s, n);
}
- if ((flags & GVRENDER_DOES_TARGETS) && ((s = agget(n, "target")) && s[0])) {
- obj->target = strdup_and_subst_node(s, n);
- }
if (flags & GVRENDER_DOES_TOOLTIPS) {
if ((s = agget(n, "tooltip")) && s[0])
obj->tooltip = strdup_and_subst_node(s, n);
else
obj->tooltip = strdup(ND_label(n)->text);
}
+ if ((flags & GVRENDER_DOES_TARGETS) && ((s = agget(n, "target")) && s[0])) {
+ obj->target = strdup_and_subst_node(s, n);
+ }
if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
/* checking shape of node */
* circle, ellipse, polygon with n side, or point.
* For regular rectangular shape we have use node's bounding box to map clickable region
*/
- if (poly && !rect && (flags & GVRENDER_DOES_MAP_POLY)) {
+ if (poly && !rect && (flags & GVRENDER_DOES_MAP_POLYGON)) {
if (poly->sides < 3)
sides = 1;
vertices = poly->vertices;
+ if ((s = agget(n, "samplepoints")))
+ nump = atoi(s);
+ /* We want at least 4 points. For server-side maps, at most 100
+ * points are allowed. To simplify things to fit with the 120 points
+ * used for skewed ellipses, we set the bound at 60.
+ */
+ if ((nump < 4) || (nump > 60))
+ nump = DFLT_SAMPLE;
/* use bounding box of text label for mapping
* when polygon has no peripheries and node is not filled
*/
if (poly->peripheries == 0 && !filled) {
- obj->url_map_shapename = "rect";
+ obj->url_map_shape = MAP_RECTANGLE;
nump = 2;
p = N_NEW(nump, pointf);
ldimen = ND_label(n)->dimen;
/* circle or ellipse */
else if (poly->sides < 3 && poly->skew == 0.0 && poly->distortion == 0.0) {
if (poly->regular) {
- obj->url_map_shapename = "circle"; /* circle */
+ obj->url_map_shape = MAP_CIRCLE;
nump = 2; /* center of circle and top right corner of bb */
p = N_NEW(nump, pointf);
p[0].x = coord.x;
p[1].y = coord.y + vertices[peripheries - 1].y;
}
else { /* ellipse is treated as polygon */
- obj->url_map_shapename = "poly"; /* ellipse */
- nump = sample;
+ obj->url_map_shape= MAP_POLYGON;
p = pEllipse((double)(vertices[peripheries - 1].x),
- (double)(vertices[peripheries - 1].y),
- nump);
+ (double)(vertices[peripheries - 1].y), nump);
for (i = 0; i < nump; i++) {
p[i].x += coord.x;
p[i].y += coord.y;
/* all other polygonal shape */
else {
int offset = (peripheries - 1)*(poly->sides);
- obj->url_map_shapename = "poly";
+ obj->url_map_shape = MAP_POLYGON;
/* distorted or skewed ellipses and circles are polygons with 120
* sides. For mapping we convert them into polygon with sample sides
*/
- if (poly->sides >= sample) {
- int delta = poly->sides / sample;
- nump = sample;
+ if (poly->sides >= nump) {
+ int delta = poly->sides / nump;
p = N_NEW(nump, pointf);
for (i = 0, j = 0; j < nump; i += delta, j++) {
p[j].x = coord.x + vertices[i + offset].x;
/* we have to use the node's bounding box to map clickable region
* when requested output format is not capable of polygons.
*/
- obj->url_map_shapename = "rect";
+ obj->url_map_shape = MAP_RECTANGLE;
nump = 2;
p = N_NEW(nump, pointf);
p[0].x = coord.x - ND_lw_i(n);
p[1].x = coord.x + ND_rw_i(n);
p[1].y = coord.y + (ND_ht_i(n) / 2);
}
+ if (! (flags & GVRENDER_DOES_TRANSFORM))
+ gvrender_ptf_A(job, p, p, nump);
obj->url_map_p = p;
obj->url_map_n = nump;
}
if (gvre) {
+ if (gvre->begin_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->begin_anchor(job, obj->url, obj->tooltip, obj->target);
if (gvre->begin_node)
gvre->begin_node(job);
}
codegen_t *cg = job->codegen;
Obj = NODE;
+ if (cg && cg->begin_anchor && (obj->url || obj->explicit_tooltip))
+ cg->begin_anchor(obj->url, obj->tooltip, obj->target);
if (cg && cg->begin_node)
cg->begin_node(n);
}
void gvrender_end_node(GVJ_t * job)
{
gvrender_engine_t *gvre = job->render.engine;
+ obj_state_t *obj = job->obj;
if (gvre) {
if (gvre->end_node)
gvre->end_node(job);
+ if (gvre->end_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->end_anchor(job);
}
#ifdef WITH_CODEGENS
else {
if (cg && cg->end_node)
cg->end_node();
+ if (cg && cg->end_anchor && (obj->url || obj->explicit_tooltip))
+ cg->end_anchor();
}
Obj = NONE;
#endif
*/
static void map_bspline_poly(pointf **pbs_p, int **pbs_n, int *pbs_poly_n, int n, pointf* p1, pointf* p2)
{
- int i, nump = 0, last = 2*n-1;
+ int i = 0, nump = 0, last = 2*n-1;
- for ( i = 0; i < *pbs_poly_n; i++)
+ for ( ; i < *pbs_poly_n; i++)
nump += (*pbs_n)[i];
(*pbs_poly_n)++;
*pbs_n = grealloc(*pbs_n, (*pbs_poly_n) * sizeof(int));
- (*pbs_n)[i] = n;
- *pbs_p = grealloc(*pbs_p, (nump + n) * sizeof(pointf));
+ (*pbs_n)[i] = 2*n;
+ *pbs_p = grealloc(*pbs_p, (nump + 2*n) * sizeof(pointf));
for (i = 0; i < n; i++) {
(*pbs_p)[nump+i] = p1[i];
}
}
- if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
+ if (flags & GVRENDER_DOES_MAPS) {
if (((s = agget(e, "href")) && s[0]) || ((s = agget(e, "URL")) && s[0]))
obj->url = strdup_and_subst_edge(s, e);
if (((s = agget(e, "tailhref")) && s[0]) || ((s = agget(e, "tailURL")) && s[0]))
}
if (flags & GVRENDER_DOES_TOOLTIPS) {
- if ((s = agget(e, "tooltip")) && s[0])
+ if ((s = agget(e, "tooltip")) && s[0]) {
obj->tooltip = strdup_and_subst_edge(s, e);
+ obj->explicit_tooltip = true;
+ }
else if (obj->label)
obj->tooltip = strdup(obj->label);
- if ((s = agget(e, "tailtooltip")) && s[0])
+ if ((s = agget(e, "tailtooltip")) && s[0]) {
obj->tailtooltip = strdup_and_subst_edge(s, e);
+ obj->explicit_tailtooltip = true;
+ }
else if (obj->taillabel)
obj->tailtooltip = strdup(obj->taillabel);
- if ((s = agget(e, "headtooltip")) && s[0])
+ if ((s = agget(e, "headtooltip")) && s[0]) {
obj->headtooltip = strdup_and_subst_edge(s, e);
+ obj->explicit_headtooltip = true;
+ }
else if (obj->headlabel)
obj->headtooltip = strdup(obj->headlabel);
}
if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
- if (flags & (GVRENDER_DOES_MAP_RECT | GVRENDER_DOES_MAP_POLY)) {
- if (flags & GVRENDER_DOES_MAP_RECT) {
- obj->url_map_shapename = "rect";
+ if (flags & (GVRENDER_DOES_MAP_RECTANGLE | GVRENDER_DOES_MAP_POLYGON)) {
+ if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
+ obj->url_map_shape = MAP_RECTANGLE;
nump = 2;
}
- else { /* GVRENDER_DOES_MAP_POLY */
- obj->url_map_shapename = "poly";
+ else { /* GVRENDER_DOES_MAP_POLYGON */
+ obj->url_map_shape = MAP_POLYGON;
nump = 4;
}
}
}
- if (ED_spl(e) && (obj->url || obj->tooltip) && (flags & GVRENDER_DOES_MAP_POLY)) {
+ if (ED_spl(e) && (obj->url || obj->tooltip) && (flags & GVRENDER_DOES_MAP_POLYGON)) {
int ns;
splines *spl;
gvrender_ptf_A(job, pbs, pbs, nump);
}
}
- if (! (flags & GVRENDER_DOES_MAP_RECT)) {
+ if (! (flags & GVRENDER_DOES_MAP_RECTANGLE)) {
if (p) rect2poly(p);
if (pt) rect2poly(pt);
if (ph) rect2poly(ph);
}
if (gvre) {
+ if (gvre->begin_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->begin_anchor(job, obj->url, obj->tooltip, obj->target);
if (gvre->begin_edge)
gvre->begin_edge(job);
}
codegen_t *cg = job->codegen;
Obj = EDGE;
+ if (cg && cg->begin_anchor && (obj->url || obj->explicit_tooltip))
+ cg->begin_anchor(obj->url, obj->tooltip, obj->target);
if (cg && cg->begin_edge)
cg->begin_edge(e);
}
void gvrender_end_edge(GVJ_t * job)
{
gvrender_engine_t *gvre = job->render.engine;
+ obj_state_t *obj = job->obj;
if (gvre) {
if (gvre->end_edge)
gvre->end_edge(job);
+ if (gvre->end_anchor && (obj->url || obj->explicit_tooltip))
+ gvre->end_anchor(job);
}
#ifdef WITH_CODEGENS
else {
if (cg && cg->end_edge)
cg->end_edge();
+ if (cg && cg->end_anchor && (obj->url || obj->explicit_tooltip))
+ cg->end_anchor();
}
Obj = NONE;
#endif
#endif
}
-void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip,
- char *target)
+void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target)
{
gvrender_engine_t *gvre = job->render.engine;
#include "gvplugin_loadimage.h"
+/* for n->name */
+#include "graph.h"
+
extern void svggen_fputs(GVJ_t * job, char *s);
extern void svggen_printf(GVJ_t * job, const char *format, ...);
typedef enum {
FORMAT_PNG_SVG, FORMAT_GIF_SVG, FORMAT_JPEG_SVG,
+ FORMAT_PNG_VRML, FORMAT_GIF_VRML, FORMAT_JPEG_VRML,
FORMAT_PS_PS, FORMAT__PS,
} format_type;
svggen_fputs(job, "/>\n");
}
+static void core_loadimage_vrml(GVJ_t * job, usershape_t *us, boxf b, bool filled)
+{
+ FILE *out;
+ obj_state_t *obj;
+ node_t *n;
+
+ assert(job);
+
+ out = job->output_file;
+ obj = job->obj;
+ assert(out);
+ assert(obj);
+
+ assert(us);
+ assert(us->name);
+ assert(us->f);
+
+ n = job->obj->n;
+ assert(n);
+
+ fprintf(out, "Shape {\n");
+ fprintf(out, " appearance Appearance {\n");
+ fprintf(out, " material Material {\n");
+ fprintf(out, " ambientIntensity 0.33\n");
+ fprintf(out, " diffuseColor 1 1 1\n");
+ fprintf(out, " }\n");
+ fprintf(out, " texture ImageTexture { url \"%s\" }\n", us->name);
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+
+
+}
+
static void ps_freeimage(usershape_t *us)
{
#if HAVE_SYS_MMAN_H
core_loadimage_svg
};
+static gvloadimage_engine_t engine_vrml = {
+ core_loadimage_vrml
+};
+
static gvloadimage_engine_t engine_ps = {
core_loadimage_ps
};
{FORMAT_PNG_SVG, "png2svg", 1, &engine_svg, NULL},
{FORMAT_GIF_SVG, "gif2svg", 1, &engine_svg, NULL},
{FORMAT_JPEG_SVG, "jpeg2svg", 1, &engine_svg, NULL},
+ {FORMAT_PNG_VRML, "png2vrml", 1, &engine_vrml, NULL},
+ {FORMAT_GIF_VRML, "gif2vrml", 1, &engine_vrml, NULL},
+ {FORMAT_JPEG_VRML, "jpeg2vrml", 1, &engine_vrml, NULL},
{FORMAT_PS_PS, "ps2ps", 1, &engine_ps, NULL},
{FORMAT__PS, "2ps", 1, &engine_pslib, NULL},
{0, NULL, 0, NULL, NULL}
typedef enum { FORMAT_IMAP, FORMAT_ISMAP, FORMAT_CMAP, FORMAT_CMAPX, } format_type;
-static void mapgen_begin_job(GVJ_t * job)
+static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, int nump,
+ char* url, char *tooltip, char *target)
+{
+ FILE *out = job->output_file;
+ int i;
+
+ static point *A;
+ static int size_A;
+
+ if (size_A < nump) {
+ size_A = nump + 10;
+ A = realloc(A, size_A * sizeof(point));
+ }
+ for (i = 0; i < nump; i++)
+ PF2P(AF[i], A[i]);
+
+ if (job->render.id == FORMAT_IMAP) {
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ /* Y_GOES_DOWN so need UL to LR */
+ fprintf(out, "rect %s %d %d %d %d\n", url,
+ A[0].x, A[1].y, A[1].x, A[0].y);
+ break;
+ case MAP_CIRCLE:
+ fprintf(out, "circle %s %d %d %d %d\n", url,
+ A[0].x, A[0].y, (A[1].x+A[0].x), A[0].y);
+ break;
+ case MAP_POLYGON:
+ fprintf(out, "poly %s", url);
+ for (i = 0; i < nump; i++)
+ fprintf(out, " %d,%d", A[i].x, A[i].y);
+ fprintf(out, "\n");
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ } else if (job->render.id == FORMAT_ISMAP) {
+ switch (map_shape) {
+ case MAP_RECTANGLE:
+ /* Y_GOES_DOWN so need UL to LR */
+ fprintf(out, "rectangle (%d,%d) (%d,%d) %s %s\n",
+ A[0].x, A[1].y, A[1].x, A[0].y, url, tooltip);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ } else if (job->render.id == FORMAT_CMAP || job->render.id == FORMAT_CMAPX) {
+ switch (map_shape) {
+ case MAP_CIRCLE:
+ fprintf(out, "<area shape=\"circle\"");
+ break;
+ case MAP_RECTANGLE:
+ fprintf(out, "<area shape=\"rect\"");
+ break;
+ case MAP_POLYGON:
+ fprintf(out, "<area shape=\"poly\"");
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (url && url[0])
+ fprintf(out, " href=\"%s\"", xml_string(url));
+ if (target && target[0])
+ fprintf(out, " target=\"%s\"", xml_string(target));
+ if (tooltip && tooltip[0])
+ fprintf(out, " title=\"%s\"", xml_string(tooltip));
+ /*
+ * alt text is intended for the visually impaired, but such
+ * folk are not likely to be clicking around on a graph anyway.
+ * IE on the PC platform (but not on Macs) incorrectly
+ * uses (non-empty) alt strings instead of title strings for tooltips.
+ * To make tooltips work and avoid this IE issue,
+ * while still satisfying usability guidelines
+ * that require that there is always an alt string,
+ * we generate just an empty alt string.
+ */
+ fprintf(out, " alt=\"\"");
+
+ fprintf(out, " coords=\"");
+ switch (map_shape) {
+ case MAP_CIRCLE:
+ fprintf(out, "%d,%d,%d", A[0].x, A[0].y, A[1].x);
+ break;
+ case MAP_RECTANGLE:
+ /* Y_GOES_DOWN so need UL to LR */
+ fprintf(out, "%d,%d,%d,%d", A[0].x, A[1].y, A[1].x, A[0].y);
+ break;
+ case MAP_POLYGON:
+ fprintf(out, "%d,%d", A[0].x, A[0].y);
+ for (i = 1; i < nump; i++)
+ fprintf(out, " %d,%d", A[i].x, A[i].y);
+ break;
+ default:
+ break;
+ }
+ if (job->render.id == FORMAT_CMAPX)
+ fprintf(out, "\"/>\n");
+ else
+ fprintf(out, "\">\n");
+ }
+}
+
+static void map_begin_job(GVJ_t * job)
{
switch (job->render.id) {
case FORMAT_IMAP:
}
}
-static void mapgen_begin_page(GVJ_t * job)
+static void map_begin_page(GVJ_t * job)
{
obj_state_t *obj = job->obj;
char *name = xml_string(obj->g->name);
switch (job->render.id) {
+ case FORMAT_IMAP:
+ if (obj->url)
+ fprintf(job->output_file, "default %s\n", obj->url);
+ break;
+ case FORMAT_ISMAP:
+ if (obj->url)
+ fprintf(job->output_file, "default %s %s\n", obj->url, obj->g->name);
+ break;
case FORMAT_CMAPX:
fprintf(job->output_file, "<map id=\"%s\" name=\"%s\">\n", name, name);
break;
default:
break;
}
- if (obj->url) {
- switch (job->render.id) {
- case FORMAT_IMAP:
- fprintf(job->output_file, "default %s\n", obj->url);
- break;
- case FORMAT_ISMAP:
- fprintf(job->output_file, "default %s %s\n", obj->url, obj->g->name);
- break;
- case FORMAT_CMAP:
- case FORMAT_CMAPX:
- /* FIXME */
- break;
- default:
- break;
- }
- }
}
-static void mapgen_end_page(GVJ_t * job)
+static void map_end_page(GVJ_t * job)
{
+ obj_state_t *obj = job->obj;
+
switch (job->render.id) {
case FORMAT_CMAPX:
+ if (obj->url_map_p)
+ map_output_shape(job, obj->url_map_shape, obj->url_map_p,obj->url_map_n,
+ obj->url, obj->tooltip, obj->target);
fprintf(job->output_file, "</map>\n");
break;
default:
}
}
-static void mapgen_begin_cluster(GVJ_t * job)
+static void map_begin_cluster(GVJ_t * job)
{
obj_state_t *obj = job->obj;
fprintf(job->output_file, "%% %s\n", obj->sg->name);
- if (obj->url) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->url_map_p[0].x, obj->url_map_p[0].y,
- obj->url_map_p[1].x, obj->url_map_p[1].y);
- }
+ if (obj->url_map_p)
+ map_output_shape(job, obj->url_map_shape, obj->url_map_p, obj->url_map_n,
+ obj->url, obj->tooltip, obj->target);
}
-static void mapgen_begin_node(GVJ_t * job)
+static void map_begin_node(GVJ_t * job)
{
obj_state_t *obj = job->obj;
- if (obj->url_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->url_map_p[0].x, obj->url_map_p[0].y,
- obj->url_map_p[1].x, obj->url_map_p[1].y);
- }
+ if (obj->url_map_p)
+ map_output_shape(job, obj->url_map_shape, obj->url_map_p,obj->url_map_n,
+ obj->url, obj->tooltip, obj->target);
}
static void
-mapgen_begin_edge(GVJ_t * job)
+map_begin_edge(GVJ_t * job)
{
obj_state_t *obj = job->obj;
+ int i, j = 0;
- if (obj->url_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->url_map_p[0].x, obj->url_map_p[0].y,
- obj->url_map_p[1].x, obj->url_map_p[1].y);
- }
- if (obj->tailurl_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->tailurl_map_p[0].x, obj->tailurl_map_p[0].y,
- obj->tailurl_map_p[1].x, obj->tailurl_map_p[1].y);
- }
- if (obj->headurl_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->headurl_map_p[0].x, obj->headurl_map_p[0].y,
- obj->headurl_map_p[1].x, obj->headurl_map_p[1].y);
- }
- if (obj->tailendurl_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->tailendurl_map_p[0].x, obj->tailendurl_map_p[0].y,
- obj->tailendurl_map_p[1].x, obj->tailendurl_map_p[1].y);
- }
- if (obj->headendurl_map_p) {
- fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
- obj->headendurl_map_p[0].x, obj->headendurl_map_p[0].y,
- obj->headendurl_map_p[1].x, obj->headendurl_map_p[1].y);
+ if (obj->url_map_p)
+ map_output_shape(job, obj->url_map_shape, obj->url_map_p, obj->url_map_n,
+ obj->url, obj->tooltip, obj->target);
+
+ if (obj->tailurl_map_p)
+ map_output_shape(job, MAP_RECTANGLE, obj->tailurl_map_p, 2,
+ obj->tailurl, obj->tailtooltip, obj->tailtarget);
+ if (obj->headurl_map_p)
+ map_output_shape(job, MAP_RECTANGLE, obj->headurl_map_p, 2,
+ obj->headurl, obj->headtooltip, obj->headtarget);
+
+ if (obj->tailendurl_map_p)
+ map_output_shape(job, MAP_RECTANGLE, obj->tailendurl_map_p,2,
+ obj->url, obj->tooltip, obj->target);
+ if (obj->headendurl_map_p)
+ map_output_shape(job, MAP_RECTANGLE, obj->headendurl_map_p, 2,
+ obj->url, obj->tooltip, obj->target);
+
+ for (i = 0; i < obj->url_bsplinemap_poly_n; i++) {
+ map_output_shape(job, MAP_POLYGON, obj->url_bsplinemap_p+j, obj->url_bsplinemap_n[i],
+ obj->url, obj->tooltip, obj->target);
+ j += obj->url_bsplinemap_n[i];
}
}
-static gvrender_engine_t mapgen_engine = {
- mapgen_begin_job,
- 0, /* mapgen_end_job */
- 0, /* mapgen_begin_graph */
- 0, /* mapgen_end_graph */
- 0, /* mapgen_begin_layer */
- 0, /* mapgen_end_layer */
- mapgen_begin_page,
- mapgen_end_page,
- mapgen_begin_cluster,
- 0, /* mapgen_end_cluster */
- 0, /* mapgen_begin_nodes */
- 0, /* mapgen_end_nodes */
- 0, /* mapgen_begin_edges */
- 0, /* mapgen_end_edges */
- mapgen_begin_node,
- 0, /* mapgen_end_node */
- mapgen_begin_edge,
- 0, /* mapgen_end_edge */
- 0, /* mapgen_begin_anchor */
- 0, /* mapgen_end_anchor */
- 0, /* mapgen_textpara */
- 0, /* mapgen_resolve_color */
- 0, /* mapgen_ellipse */
- 0, /* mapgen_polygon */
- 0, /* mapgen_bezier */
- 0, /* mapgen_polyline */
- 0, /* mapgen_comment */
+static gvrender_engine_t map_engine = {
+ map_begin_job,
+ 0, /* map_end_job */
+ 0, /* map_begin_graph */
+ 0, /* map_end_graph */
+ 0, /* map_begin_layer */
+ 0, /* map_end_layer */
+ map_begin_page,
+ map_end_page,
+ map_begin_cluster,
+ 0, /* map_end_cluster */
+ 0, /* map_begin_nodes */
+ 0, /* map_end_nodes */
+ 0, /* map_begin_edges */
+ 0, /* map_end_edges */
+ map_begin_node,
+ 0, /* map_end_node */
+ map_begin_edge,
+ 0, /* map_end_edge */
+ 0, /* map_begin_anchor */
+ 0, /* map_end_anchor */
+ 0, /* map_textpara */
+ 0, /* map_resolve_color */
+ 0, /* map_ellipse */
+ 0, /* map_polygon */
+ 0, /* map_bezier */
+ 0, /* map_polyline */
+ 0, /* map_comment */
};
-static gvrender_features_t mapgen_features_poly = {
- GVRENDER_DOES_MAPS
- | GVRENDER_DOES_MAP_RECT
- | GVRENDER_DOES_MAP_POLY,
+static gvrender_features_t map_features_poly = {
+ GVRENDER_Y_GOES_DOWN
+ | GVRENDER_DOES_MAPS
+ | GVRENDER_DOES_LABELS
+ | GVRENDER_DOES_TOOLTIPS
+ | GVRENDER_DOES_TARGETS
+ | GVRENDER_DOES_MAP_RECTANGLE
+ | GVRENDER_DOES_MAP_CIRCLE
+ | GVRENDER_DOES_MAP_POLYGON,
0, /* default margin - points */
- {72.,72.}, /* default dpi */
+ {96.,96.}, /* default dpi */
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
NULL, /* gvloadimage target for usershapes */
};
-static gvrender_features_t mapgen_features = {
- GVRENDER_DOES_MAPS
- | GVRENDER_DOES_MAP_RECT,
+static gvrender_features_t map_features = {
+ GVRENDER_Y_GOES_DOWN
+ | GVRENDER_DOES_MAPS
+ | GVRENDER_DOES_LABELS
+ | GVRENDER_DOES_TOOLTIPS
+ | GVRENDER_DOES_MAP_RECTANGLE,
0, /* default margin - points */
- {72.,72.}, /* default dpi */
+ {96.,96.}, /* default dpi */
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
};
gvplugin_installed_t gvrender_core_map_types[] = {
- {FORMAT_IMAP, "imap", -1, &mapgen_engine, &mapgen_features_poly},
- {FORMAT_ISMAP, "ismap", -1, &mapgen_engine, &mapgen_features},
- {FORMAT_CMAP, "cmap", -1, &mapgen_engine, &mapgen_features},
- {FORMAT_CMAPX, "cmapx", -1, &mapgen_engine, &mapgen_features_poly},
+ {FORMAT_ISMAP, "ismap", 1, &map_engine, &map_features},
+ {FORMAT_IMAP, "imap", 1, &map_engine, &map_features_poly},
+ {FORMAT_CMAP, "cmap", 1, &map_engine, &map_features_poly},
+ {FORMAT_CMAPX, "cmapx", 1, &map_engine, &map_features_poly},
{0, NULL, 0, NULL, NULL}
};
GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES
| GVRENDER_DOES_TRANSFORM
| GVRENDER_DOES_MAPS
- | GVRENDER_DOES_MAP_RECT,
+ | GVRENDER_DOES_MAP_RECTANGLE,
36, /* default margin - points */
{72.,72.}, /* default dpi */
NULL, /* knowncolors */
static void vrml_end_node(GVJ_t *job)
{
- obj_state_t *obj = job->obj;
- node_t *n = obj->n;
-
- if (shapeOf(n) != SH_POINT) {
+ if (im) {
gdImagePng(im, PNGfile);
gdImageDestroy(im);
im = NULL;
p.x -= para->width / 2;
break;
}
-/* p.y += cstk[SP].fontsz*2/3; */
mp = vrml_node_point(job, obj->n, p);
0, /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
NULL, /* device */
- NULL, /* gvloadimage target for usershapes */
+ "vrml", /* gvloadimage target for usershapes */
};
#endif /* HAVE_GD_PNG */
#endif /* HAVE_LIBGD */