static void svg_begin_edge(GVJ_t * job) { obj_state_t *obj = job->obj; char *ename; svg_print_id_class(job, obj->id, NULL, "edge", obj->u.e); gvputs(job, ">\n"); gvputs(job, "<title>"); ename = strdup_and_subst_obj("\\E", (void *) (obj->u.e)); gvputs(job, xml_string(ename)); free(ename); gvputs(job, "</title>\n"); }
static void svg_begin_edge(GVJ_t * job) { obj_state_t *obj = job->obj; char *ename; gvputs(job, "<g id=\""); gvputs(job, xml_string(obj->id)); gvputs(job, "\" class=\"edge\">"); gvputs(job, "<title>"); ename = strdup_and_subst_obj("\\E", (void *) (obj->u.e)); gvputs(job, xml_string(ename)); free(ename); gvputs(job, "</title>\n"); }
/* cgraph requires */ void graph_init(graph_t * g, boolean use_rankdir) { char *p; double xf; static char *rankname[] = { "local", "global", "none", NULL }; static int rankcode[] = { LOCAL, GLOBAL, NOCLUST, LOCAL }; static char *fontnamenames[] = {"gd","ps","svg", NULL}; static int fontnamecodes[] = {NATIVEFONTS,PSFONTS,SVGFONTS,-1}; int rankdir; GD_drawing(g) = NEW(layout_t); /* set this up fairly early in case any string sizes are needed */ if ((p = agget(g, "fontpath")) || (p = getenv("DOTFONTPATH"))) { /* overide GDFONTPATH in local environment if dot * wants its own */ #ifdef HAVE_SETENV setenv("GDFONTPATH", p, 1); #else static char *buf = 0; buf = grealloc(buf, strlen("GDFONTPATH=") + strlen(p) + 1); strcpy(buf, "GDFONTPATH="); strcat(buf, p); putenv(buf); #endif } GD_charset(g) = findCharset (g); if (!HTTPServerEnVar) { Gvimagepath = agget (g, "imagepath"); if (!Gvimagepath) Gvimagepath = Gvfilepath; } GD_drawing(g)->quantum = late_double(g, agfindgraphattr(g, "quantum"), 0.0, 0.0); /* setting rankdir=LR is only defined in dot, * but having it set causes shape code and others to use it. * The result is confused output, so we turn it off unless requested. * This effective rankdir is stored in the bottom 2 bits of g->u.rankdir. * Sometimes, the code really needs the graph's rankdir, e.g., neato -n * with record shapes, so we store the real rankdir in the next 2 bits. */ rankdir = RANKDIR_TB; if ((p = agget(g, "rankdir"))) { if (streq(p, "LR")) rankdir = RANKDIR_LR; else if (streq(p, "BT")) rankdir = RANKDIR_BT; else if (streq(p, "RL")) rankdir = RANKDIR_RL; } if (use_rankdir) SET_RANKDIR (g, (rankdir << 2) | rankdir); else SET_RANKDIR (g, (rankdir << 2)); xf = late_double(g, agfindgraphattr(g, "nodesep"), DEFAULT_NODESEP, MIN_NODESEP); GD_nodesep(g) = POINTS(xf); p = late_string(g, agfindgraphattr(g, "ranksep"), NULL); if (p) { if (sscanf(p, "%lf", &xf) == 0) xf = DEFAULT_RANKSEP; else { if (xf < MIN_RANKSEP) xf = MIN_RANKSEP; } if (strstr(p, "equally")) GD_exact_ranksep(g) = TRUE; } else xf = DEFAULT_RANKSEP; GD_ranksep(g) = POINTS(xf); GD_showboxes(g) = late_int(g, agfindgraphattr(g, "showboxes"), 0, 0); p = late_string(g, agfindgraphattr(g, "fontnames"), NULL); GD_fontnames(g) = maptoken(p, fontnamenames, fontnamecodes); setRatio(g); GD_drawing(g)->filled = getdoubles2ptf(g, "size", &(GD_drawing(g)->size)); getdoubles2ptf(g, "page", &(GD_drawing(g)->page)); GD_drawing(g)->centered = mapbool(agget(g, "center")); if ((p = agget(g, "rotate"))) GD_drawing(g)->landscape = (atoi(p) == 90); else if ((p = agget(g, "orientation"))) GD_drawing(g)->landscape = ((p[0] == 'l') || (p[0] == 'L')); else if ((p = agget(g, "landscape"))) GD_drawing(g)->landscape = mapbool(p); p = agget(g, "clusterrank"); CL_type = maptoken(p, rankname, rankcode); p = agget(g, "concentrate"); Concentrate = mapbool(p); State = GVBEGIN; EdgeLabelsDone = 0; GD_drawing(g)->dpi = 0.0; if (((p = agget(g, "dpi")) && p[0]) || ((p = agget(g, "resolution")) && p[0])) GD_drawing(g)->dpi = atof(p); do_graph_label(g); Initial_dist = MYHUGE; G_ordering = agfindgraphattr(g, "ordering"); G_gradientangle = agfindgraphattr(g,"gradientangle"); G_margin = agfindgraphattr(g, "margin"); /* initialize nodes */ N_height = agfindnodeattr(g, "height"); N_width = agfindnodeattr(g, "width"); N_shape = agfindnodeattr(g, "shape"); N_color = agfindnodeattr(g, "color"); N_fillcolor = agfindnodeattr(g, "fillcolor"); N_style = agfindnodeattr(g, "style"); N_fontsize = agfindnodeattr(g, "fontsize"); N_fontname = agfindnodeattr(g, "fontname"); N_fontcolor = agfindnodeattr(g, "fontcolor"); N_label = agfindnodeattr(g, "label"); if (!N_label) N_label = agattr(g, AGNODE, "label", NODENAME_ESC); N_xlabel = agfindnodeattr(g, "xlabel"); N_showboxes = agfindnodeattr(g, "showboxes"); N_penwidth = agfindnodeattr(g, "penwidth"); N_ordering = agfindnodeattr(g, "ordering"); N_margin = agfindnodeattr(g, "margin"); /* attribs for polygon shapes */ N_sides = agfindnodeattr(g, "sides"); N_peripheries = agfindnodeattr(g, "peripheries"); N_skew = agfindnodeattr(g, "skew"); N_orientation = agfindnodeattr(g, "orientation"); N_distortion = agfindnodeattr(g, "distortion"); N_fixed = agfindnodeattr(g, "fixedsize"); N_imagescale = agfindnodeattr(g, "imagescale"); N_nojustify = agfindnodeattr(g, "nojustify"); N_layer = agfindnodeattr(g, "layer"); N_group = agfindnodeattr(g, "group"); N_comment = agfindnodeattr(g, "comment"); N_vertices = agfindnodeattr(g, "vertices"); N_z = agfindnodeattr(g, "z"); N_gradientangle = agfindnodeattr(g,"gradientangle"); /* initialize edges */ E_weight = agfindedgeattr(g, "weight"); E_color = agfindedgeattr(g, "color"); E_fillcolor = agfindedgeattr(g, "fillcolor"); E_fontsize = agfindedgeattr(g, "fontsize"); E_fontname = agfindedgeattr(g, "fontname"); E_fontcolor = agfindedgeattr(g, "fontcolor"); E_label = agfindedgeattr(g, "label"); E_xlabel = agfindedgeattr(g, "xlabel"); E_label_float = agfindedgeattr(g, "labelfloat"); /* vladimir */ E_dir = agfindedgeattr(g, "dir"); E_arrowhead = agfindedgeattr(g, "arrowhead"); E_arrowtail = agfindedgeattr(g, "arrowtail"); E_headlabel = agfindedgeattr(g, "headlabel"); E_taillabel = agfindedgeattr(g, "taillabel"); E_labelfontsize = agfindedgeattr(g, "labelfontsize"); E_labelfontname = agfindedgeattr(g, "labelfontname"); E_labelfontcolor = agfindedgeattr(g, "labelfontcolor"); E_labeldistance = agfindedgeattr(g, "labeldistance"); E_labelangle = agfindedgeattr(g, "labelangle"); /* end vladimir */ E_minlen = agfindedgeattr(g, "minlen"); E_showboxes = agfindedgeattr(g, "showboxes"); E_style = agfindedgeattr(g, "style"); E_decorate = agfindedgeattr(g, "decorate"); E_arrowsz = agfindedgeattr(g, "arrowsize"); E_constr = agfindedgeattr(g, "constraint"); E_layer = agfindedgeattr(g, "layer"); E_comment = agfindedgeattr(g, "comment"); E_tailclip = agfindedgeattr(g, "tailclip"); E_headclip = agfindedgeattr(g, "headclip"); E_penwidth = agfindedgeattr(g, "penwidth"); /* background */ GD_drawing(g)->xdots = init_xdot (g); /* initialize id, if any */ if ((p = agget(g, "id")) && *p) GD_drawing(g)->id = strdup_and_subst_obj(p, g); }
/* do_graph_label: * Set characteristics of graph label if it exists. * */ void do_graph_label(graph_t * sg) { char *p, *pos, *just; int pos_ix; /* it would be nice to allow multiple graph labels in the future */ if ((p = agget(sg, "label"))) { char pos_flag; int lbl_kind = LT_NONE; point dpt; pointf dimen; if (aghtmlstr(p)) lbl_kind = LT_HTML; GD_has_labels(sg->root) |= GRAPH_LABEL; if (lbl_kind) p = strdup (p); else p = strdup_and_subst_obj(p, (void*)sg); GD_label(sg) = make_label(sg->root, lbl_kind, p, late_double(sg, agfindattr(sg, "fontsize"), DEFAULT_FONTSIZE, MIN_FONTSIZE), late_nnstring(sg, agfindattr(sg, "fontname"), DEFAULT_FONTNAME), late_nnstring(sg, agfindattr(sg, "fontcolor"), DEFAULT_COLOR)); if (lbl_kind) { if (make_html_label(sg->root, GD_label(sg), sg) == 1) agerr(AGPREV, "in label of graph %s\n", sg->name); } /* set label position */ pos = agget(sg, "labelloc"); if (sg != sg->root) { if (pos && (pos[0] == 'b')) pos_flag = LABEL_AT_BOTTOM; else pos_flag = LABEL_AT_TOP; } else { if (pos && (pos[0] == 't')) pos_flag = LABEL_AT_TOP; else pos_flag = LABEL_AT_BOTTOM; } just = agget(sg, "labeljust"); if (just) { if (just[0] == 'l') pos_flag |= LABEL_AT_LEFT; else if (just[0] == 'r') pos_flag |= LABEL_AT_RIGHT; } GD_label_pos(sg) = pos_flag; if (sg == sg->root) return; /* Set border information for cluster labels to allow space */ dimen = GD_label(sg)->dimen; PAD(dimen); PF2P(dimen, dpt); if (!GD_flip(sg->root)) { if (GD_label_pos(sg) & LABEL_AT_TOP) pos_ix = TOP_IX; else pos_ix = BOTTOM_IX; GD_border(sg)[pos_ix] = dpt; } else { /* when rotated, the labels will be restored to TOP or BOTTOM */ if (GD_label_pos(sg) & LABEL_AT_TOP) pos_ix = RIGHT_IX; else pos_ix = LEFT_IX; GD_border(sg)[pos_ix].x = dpt.y; GD_border(sg)[pos_ix].y = dpt.x; } } }
static void gv_graph_state(GVJ_t *job, graph_t *g) { #ifndef WITH_CGRAPH int i; #endif int j; Agsym_t *a; gv_argvlist_t *list; list = &(job->selected_obj_type_name); j = 0; if (g == agroot(g)) { if (agisdirected(g)) gv_argvlist_set_item(list, j++, s_digraph); else gv_argvlist_set_item(list, j++, s_graph); } else { gv_argvlist_set_item(list, j++, s_subgraph); } gv_argvlist_set_item(list, j++, agnameof(g)); list->argc = j; list = &(job->selected_obj_attributes); #ifndef WITH_CGRAPH for (i = 0, j = 0; i < dtsize(g->univ->globattr->dict); i++) { a = g->univ->globattr->list[i]; #else a = NULL; while ((a = agnxtattr(g, AGRAPH, a))) { #endif gv_argvlist_set_item(list, j++, a->name); #ifndef WITH_CGRAPH gv_argvlist_set_item(list, j++, agxget(g, a->index)); #else gv_argvlist_set_item(list, j++, agxget(g, a)); #endif gv_argvlist_set_item(list, j++, (char*)GVATTR_STRING); } list->argc = j; a = agfindgraphattr(g, s_href); if (!a) a = agfindgraphattr(g, s_URL); if (a) #ifndef WITH_CGRAPH job->selected_href = strdup_and_subst_obj(agxget(g, a->index), (void*)g); #else job->selected_href = strdup_and_subst_obj(agxget(g, a), (void*)g); #endif } static void gv_node_state(GVJ_t *job, node_t *n) { #ifndef WITH_CGRAPH int i; #endif int j; Agsym_t *a; Agraph_t *g; gv_argvlist_t *list; list = &(job->selected_obj_type_name); j = 0; gv_argvlist_set_item(list, j++, s_node); gv_argvlist_set_item(list, j++, agnameof(n)); list->argc = j; list = &(job->selected_obj_attributes); g = agroot(agraphof(n)); #ifndef WITH_CGRAPH for (i = 0, j = 0; i < dtsize(g->univ->nodeattr->dict); i++) { a = g->univ->nodeattr->list[i]; #else a = NULL; while ((a = agnxtattr(g, AGNODE, a))) { #endif gv_argvlist_set_item(list, j++, a->name); #ifndef WITH_CGRAPH gv_argvlist_set_item(list, j++, agxget(n, a->index)); #else gv_argvlist_set_item(list, j++, agxget(n, a)); #endif } list->argc = j; a = agfindnodeattr(agraphof(n), s_href); if (!a) a = agfindnodeattr(agraphof(n), s_URL); if (a) #ifndef WITH_CGRAPH job->selected_href = strdup_and_subst_obj(agxget(n, a->index), (void*)n); #else job->selected_href = strdup_and_subst_obj(agxget(n, a), (void*)n); #endif } static void gv_edge_state(GVJ_t *job, edge_t *e) { #ifndef WITH_CGRAPH int i; #endif int j; Agsym_t *a; Agraph_t *g; gv_argvlist_t *nlist, *alist; nlist = &(job->selected_obj_type_name); /* only tail, head, and key are strictly identifying properties, * but we commonly alse use edge kind (e.g. "->") and tailport,headport * in edge names */ j = 0; gv_argvlist_set_item(nlist, j++, s_edge); gv_argvlist_set_item(nlist, j++, agnameof(agtail(e))); j++; /* skip tailport slot for now */ gv_argvlist_set_item(nlist, j++, agisdirected(agraphof(agtail(e)))?"->":"--"); gv_argvlist_set_item(nlist, j++, agnameof(aghead(e))); j++; /* skip headport slot for now */ j++; /* skip key slot for now */ nlist->argc = j; alist = &(job->selected_obj_attributes); g = agroot(agraphof(aghead(e))); #ifndef WITH_CGRAPH for (i = 0, j = 0; i < dtsize(g->univ->edgeattr->dict); i++) { a = g->univ->edgeattr->list[i]; #else a = NULL; while ((a = agnxtattr(g, AGEDGE, a))) { #endif /* tailport and headport can be shown as part of the name, but they * are not identifying properties of the edge so we * also list them as modifyable attributes. */ if (strcmp(a->name,s_tailport) == 0) #ifndef WITH_CGRAPH gv_argvlist_set_item(nlist, 2, agxget(e, a->index)); #else gv_argvlist_set_item(nlist, 2, agxget(e, a)); #endif else if (strcmp(a->name,s_headport) == 0) #ifndef WITH_CGRAPH gv_argvlist_set_item(nlist, 5, agxget(e, a->index)); #else gv_argvlist_set_item(nlist, 5, agxget(e, a)); #endif /* key is strictly an identifying property to distinguish multiple * edges between the same node pair. Its non-writable, so * no need to list it as an attribute as well. */ else if (strcmp(a->name,s_key) == 0) { #ifndef WITH_CGRAPH gv_argvlist_set_item(nlist, 6, agxget(e, a->index)); #else gv_argvlist_set_item(nlist, 6, agxget(e, a)); #endif continue; } gv_argvlist_set_item(alist, j++, a->name); #ifndef WITH_CGRAPH gv_argvlist_set_item(alist, j++, agxget(e, a->index)); #else gv_argvlist_set_item(alist, j++, agxget(e, a)); #endif }
static int size_html_txt(graph_t *g, htmltxt_t* ftxt, htmlenv_t* env) { double xsize = 0.0; /* width of text block */ double ysize = 0.0; /* height of text block */ double fsize; double lsize; /* height of current line */ double mxfsize; /* max. font size for the current line */ double curbline = 0; /* dist. of current base line from top */ pointf sz; int i, j, w, width; char *fname; textpara_t lp; for (i = 0; i < ftxt->nparas; i++) { width = w = 0; mxfsize = 0; for (j = 0; j < ftxt->paras[i].nitems; j++) { lp.str = strdup_and_subst_obj (ftxt->paras[i].items[j].str, env->obj); if (ftxt->paras[i].items[j].font) { if (ftxt->paras[i].items[j].font->size > 0) fsize = ftxt->paras[i].items[j].font->size; else fsize = env->finfo.size; if (ftxt->paras[i].items[j].font->name) fname = ftxt->paras[i].items[j].font->name; else fname = env->finfo.name; } else { fsize = env->finfo.size; fname = env->finfo.name; } sz = textsize(g, &lp, fname, fsize); free (ftxt->paras[i].items[j].str); ftxt->paras[i].items[j].str = lp.str; ftxt->paras[i].items[j].size = sz.x; ftxt->paras[i].items[j].xshow = lp.xshow; ftxt->paras[i].items[j].postscript_alias = lp.postscript_alias; ftxt->paras[i].items[j].layout = lp.layout; ftxt->paras[i].items[j].free_layout = lp.free_layout; width += sz.x; mxfsize = MAX(fsize, mxfsize); } lsize = mxfsize * LINESPACING; ftxt->paras[i].size = (double) width; /* ysize - curbline is the distance from the previous * baseline to the bottom of the previous line. * Then, in the current line, we set the baseline to * be 5/6 of the max. font size. Thus, lfsize gives the * distance from the previous baseline to the new one. */ ftxt->paras[i].lfsize = 5*mxfsize/6 + ysize - curbline; curbline += ftxt->paras[i].lfsize; xsize = MAX(width, xsize); ysize += lsize; } ftxt->box.UR.x = xsize; if (ftxt->nparas == 1) ftxt->box.UR.y = (int) (mxfsize); else ftxt->box.UR.y = (int) (ysize); return 0; }