void common_init_node(node_t * n) { struct fontinfo fi; char *str; ND_width(n) = late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH); ND_height(n) = late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEHEIGHT); ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE), n); str = agxget(n, N_label); fi.fontsize = late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE); fi.fontname = late_nnstring(n, N_fontname, DEFAULT_FONTNAME); fi.fontcolor = late_nnstring(n, N_fontcolor, DEFAULT_COLOR); ND_label(n) = make_label((void*)n, str, ((aghtmlstr(str) ? LT_HTML : LT_NONE) | ( (shapeOf(n) == SH_RECORD) ? LT_RECD : LT_NONE)), fi.fontsize, fi.fontname, fi.fontcolor); if (N_xlabel && (str = agxget(n, N_xlabel)) && (str[0])) { ND_xlabel(n) = make_label((void*)n, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(agraphof(n)) |= NODE_XLABEL; } ND_showboxes(n) = late_int(n, N_showboxes, 0, 0); ND_shape(n)->fns->initfn(n); }
/* * canonicalize a string for printing. * must agree with strings in scan.l * Unsafe if buffer is not large enough. */ char *agstrcanon(char *arg, char *buf) { if (aghtmlstr(arg)) return agcanonhtmlstr(arg, buf); else return _agstrcanon(arg, buf); }
/* writenodeandport: */ static void writenodeandport(FILE * fp, char *node, char *port) { char *ss; agputs(agcanonical(node), fp); /* slimey i know */ if (port && *port) { if (aghtmlstr(port)) { agputc(':', fp); agputs(agstrcanon(port, getoutputbuffer(port)), fp); } else { ss = strchr (port, ':'); if (ss) { *ss = '\0'; agputc(':', fp); agputs(_agstrcanon(port, getoutputbuffer(port)), fp); agputc(':', fp); agputs(_agstrcanon(ss+1, getoutputbuffer(ss+1)), fp); *ss = ':'; } else { agputc(':', fp); agputs(_agstrcanon(port, getoutputbuffer(port)), fp); } } } }
/* copyAttr: * Copy attributes from src to tgt. Overrides currently * defined values. * FIX: we should probably use the default value of the source * graph when initializing the attribute, rather than "". * NOTE: We do not assume src and tgt have the same kind. */ int copyAttr(Agobj_t * src, Agobj_t * tgt) { Agraph_t *srcg; Agraph_t *tgtg; Agsym_t *sym = 0; Agsym_t *tsym = 0; int skind = AGTYPE(src); int tkind = AGTYPE(tgt); char* val; srcg = agraphof(src); tgtg = agraphof(tgt); while ((sym = agnxtattr(srcg, skind, sym))) { tsym = agattrsym(tgt, sym->name); if (!tsym) tsym = agattr(tgtg, tkind, sym->name, sym->defval); val = agxget(src, sym); if (aghtmlstr (val)) { val = agstrdup_html (tgtg, val); agxset(tgt, tsym, val); agstrfree (tgtg, val); } else agxset(tgt, tsym, val); } return 0; }
void GraphvizPlotter::parseEdgeAttrs(Agedge_t *e, Edge *edge, processedProperties *props) { // prochazime vsechny mozne atributy hrany for (auto i : GraphvizAttrs::edge_attrs) { char *value = agget(e, (char *) i.c_str()); // pokud by dany atribut zadan a nebyl jeste zpracovan if (value && !isWalkedObjectAttr(&props->edge_attrs, i, value)) { std::string val(value); // pokud neni atribut html, vyescapujeme hodnotu if (!aghtmlstr(value)) { val = Utility::escape_quotes(val); } // pridame atribut k hrane edge->setAttr(i.c_str(), val.c_str()); // pokud je to html, nastavime priznak if (aghtmlstr(value)) { Attribute *g_attr = edge->getAttr(i.c_str()); g_attr->setHtml(); } } } }
void GraphvizPlotter::parseNodeAttrs(Agnode_t *n, Node *node, processedProperties *props) { // prochazime vsechny dostupne atributy vrcholu for (auto i : GraphvizAttrs::node_attrs) { char *value = agget(n, (char *) i.c_str()); // pokud byl dany atribut zadan a jeste nebyl zpracovan if (value && !isWalkedObjectAttr(&props->node_attrs, i, value)) { std::string val(value); // pokud nejde o html atribut, vyescapujeme uvozovky if (!aghtmlstr(value)) { val = Utility::escape_quotes(val); } // nastaveni atributu node->setAttr(i.c_str(), val.c_str()); // pokud jde o html, nastavime priznak if (aghtmlstr(value)) { Attribute *g_attr = node->getAttr(i.c_str()); g_attr->setHtml(); } } } }
/* agstrcanon: * handles both html and ordinary strings. * canonicalize a string for printing. * changes to the semantics of this function * also involve the string scanner in lexer.c * Unsafe if buf is not large enough. */ char *agstrcanon(char *arg, char *buf) { char *s = arg; char *p = buf; if (aghtmlstr(arg)) { *p++ = '<'; while (*s) *p++ = *s++; *p++ = '>'; *p = '\0'; return buf; } else return (_agstrcanon(arg, buf)); }
//------------------------------------------------- static char* myagxget(void *obj, Agsym_t *a) { int len; char *val, *hs; if (!obj || !a) return empty_string; val = agxget(obj, a->index); if (!val) return empty_string; if (a->name[0] == 'l' && strcmp(a->name, "label") == 0 && aghtmlstr(val)) { len = strlen(val); hs = (char*)malloc(len + 3); hs[0] = '<'; strcpy(hs+1, val); hs[len+1] = '>'; hs[len+2] = '\0'; return hs; } return val; }
void common_init_node(node_t * n) { char *str; int html = 0; ND_width(n) = late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH); ND_height(n) = late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEHEIGHT); if (N_label == NULL) str = NODENAME_ESC; else { str = agxget(n, N_label->index); html = aghtmlstr(str); } if (html) str = strdup(str); else str = strdup_and_subst_node(str, n); ND_label(n) = make_label(html, str, late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE), late_nnstring(n, N_fontname, DEFAULT_FONTNAME), late_nnstring(n, N_fontcolor, DEFAULT_COLOR), n->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ND_label(n), n) == 1) agerr(AGPREV, "in label of node %s\n", n->name); } #endif ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE), n); ND_showboxes(n) = late_int(n, N_showboxes, 0, 0); ND_shape(n)->fns->initfn(n); }
/* writenodeandport: */ static void writenodeandport(FILE * fp, char *node, char *port) { char *ss; fprintf(fp, "%s", agcanonical(node)); /* slimey i know */ if (port && *port) { if (aghtmlstr(port)) { fprintf(fp, ":%s", agstrcanon(port, getoutputbuffer(port))); } else { ss = strchr (port, ':'); if (ss) { *ss = '\0'; fprintf(fp, ":%s", _agstrcanon(port, getoutputbuffer(port))); fprintf(fp, ":%s", _agstrcanon(ss+1, getoutputbuffer(ss+1))); *ss = ':'; } else { fprintf(fp, ":%s", _agstrcanon(port, getoutputbuffer(port))); } } } }
/* return TRUE if edge has label */ int common_init_edge(edge_t * e) { char *s; int html = 0, r = 0; struct fontinfo fi; struct fontinfo lfi; fi.fontname = NULL; lfi.fontname = NULL; if (E_label && (s = agxget(e, E_label->index)) && (s[0])) { r = 1; html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); initFontEdgeAttr(e, &fi); ED_label(e) = make_label(html, s, fi.fontsize, fi.fontname, fi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_label(e), e) == 1) edgeError(e, "label"); } #endif GD_has_labels(e->tail->graph) |= EDGE_LABEL; ED_label_ontop(e) = mapbool(late_string(e, E_label_float, "false")); } /* vladimir */ if (E_headlabel && (s = agxget(e, E_headlabel->index)) && (s[0])) { html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); initFontLabelEdgeAttr(e, &fi, &lfi); ED_head_label(e) = make_label(html, s, lfi.fontsize, lfi.fontname, lfi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_head_label(e), e) == 1) edgeError(e, "head label"); } #endif GD_has_labels(e->tail->graph) |= HEAD_LABEL; } if (E_taillabel && (s = agxget(e, E_taillabel->index)) && (s[0])) { html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); if (!lfi.fontname) initFontLabelEdgeAttr(e, &fi, &lfi); ED_tail_label(e) = make_label(html, s, lfi.fontsize, lfi.fontname, lfi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_tail_label(e), e) == 1) edgeError(e, "tail label"); } #endif GD_has_labels(e->tail->graph) |= TAIL_LABEL; } /* end vladimir */ /* We still accept ports beginning with colons but this is deprecated */ s = agget(e, TAIL_ID); if (s[0]) ND_has_port(e->tail) = TRUE; ED_tail_port(e) = chkPort (ND_shape(e->tail)->fns->portfn,e->tail, s); if (noClip(e, E_tailclip)) ED_tail_port(e).clip = FALSE; s = agget(e, HEAD_ID); if (s[0]) ND_has_port(e->head) = TRUE; ED_head_port(e) = chkPort(ND_shape(e->head)->fns->portfn,e->head, s); if (noClip(e, E_headclip)) ED_head_port(e).clip = FALSE; return r; }
/* do_graph_label: * Set characteristics of graph label if it exists. * */ void do_graph_label(graph_t * sg) { char *str, *pos, *just; int pos_ix; /* it would be nice to allow multiple graph labels in the future */ if ((str = agget(sg, "label")) && (*str != '\0')) { char pos_flag; pointf dimen; GD_has_labels(sg->root) |= GRAPH_LABEL; GD_label(sg) = make_label((void*)sg, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), late_double(sg, agfindgraphattr(sg, "fontsize"), DEFAULT_FONTSIZE, MIN_FONTSIZE), late_nnstring(sg, agfindgraphattr(sg, "fontname"), DEFAULT_FONTNAME), late_nnstring(sg, agfindgraphattr(sg, "fontcolor"), DEFAULT_COLOR)); /* set label position */ pos = agget(sg, "labelloc"); if (sg != agroot(sg)) { 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 == agroot(sg)) return; /* Set border information for cluster labels to allow space */ dimen = GD_label(sg)->dimen; PAD(dimen); if (!GD_flip(agroot(sg))) { if (GD_label_pos(sg) & LABEL_AT_TOP) pos_ix = TOP_IX; else pos_ix = BOTTOM_IX; GD_border(sg)[pos_ix] = dimen; } 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 = dimen.y; GD_border(sg)[pos_ix].y = dimen.x; } } }
/* do_graph_label: * If the ifdef'ed parts are added, clusters are guaranteed not * to overlap and have sufficient room for the label. The problem * is this approach does not use the actual size of the cluster, so * the resulting cluster tends to be far too large. */ void do_graph_label(graph_t* sg) { char *p, *pos, *just; int pos_ix; GVC_t *gvc = GD_gvc(sg->root); /* it would be nice to allow multiple graph labels in the future */ if ((p = agget(sg,"label"))) { char pos_flag; int html = aghtmlstr(p); GD_has_labels(sg->root) |= GRAPH_LABEL; GD_label(sg) = make_label(gvc, html,strdup_and_subst_graph(p,sg), 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),sg); if (html) { if (make_html_label(gvc, GD_label(sg), sg)) 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(!GD_left_to_right(sg->root)) { point dpt; dpt = cvt2pt(GD_label(sg)->dimen); if (GD_label_pos(sg) & LABEL_AT_TOP) pos_ix = TOP_IX; else pos_ix = BOTTOM_IX; GD_border(sg)[pos_ix] = dpt; #if 0 if(g != g->root) { GD_border(g)[LEFT_IX].x = dpt.x/2; GD_border(g)[RIGHT_IX].x = dpt.x/2; GD_border(g)[LEFT_IX].y = 0; GD_border(g)[RIGHT_IX].y = 0; } #endif } else { point dpt; dpt = cvt2pt(GD_label(sg)->dimen); /* 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; #if 0 if(g != g->root) { GD_border(g)[TOP_IX].y = dpt.x/2; GD_border(g)[BOTTOM_IX].y = dpt.x/2; GD_border(g)[TOP_IX].x = 0; GD_border(g)[BOTTOM_IX].x = 0; } #endif } } }
/* 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; } } }
/* return true if edge has label */ int common_init_edge(edge_t * e) { char *str; int r = 0; struct fontinfo fi; struct fontinfo lfi; graph_t *sg = agraphof(agtail(e)); fi.fontname = NULL; lfi.fontname = NULL; if (E_label && (str = agxget(e, E_label)) && (str[0])) { r = 1; initFontEdgeAttr(e, &fi); ED_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(sg) |= EDGE_LABEL; ED_label_ontop(e) = mapbool(late_string(e, E_label_float, "false")); } if (E_xlabel && (str = agxget(e, E_xlabel)) && (str[0])) { if (!fi.fontname) initFontEdgeAttr(e, &fi); ED_xlabel(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(sg) |= EDGE_XLABEL; } /* vladimir */ if (E_headlabel && (str = agxget(e, E_headlabel)) && (str[0])) { initFontLabelEdgeAttr(e, &fi, &lfi); ED_head_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), lfi.fontsize, lfi.fontname, lfi.fontcolor); GD_has_labels(sg) |= HEAD_LABEL; } if (E_taillabel && (str = agxget(e, E_taillabel)) && (str[0])) { if (!lfi.fontname) initFontLabelEdgeAttr(e, &fi, &lfi); ED_tail_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), lfi.fontsize, lfi.fontname, lfi.fontcolor); GD_has_labels(sg) |= TAIL_LABEL; } /* end vladimir */ /* We still accept ports beginning with colons but this is deprecated * That is, we allow tailport = ":abc" as well as the preferred * tailport = "abc". */ str = agget(e, TAIL_ID); /* libgraph always defines tailport/headport; libcgraph doesn't */ if (!str) str = ""; if (str && str[0]) ND_has_port(agtail(e)) = TRUE; ED_tail_port(e) = chkPort (ND_shape(agtail(e))->fns->portfn, agtail(e), str); if (noClip(e, E_tailclip)) ED_tail_port(e).clip = FALSE; str = agget(e, HEAD_ID); /* libgraph always defines tailport/headport; libcgraph doesn't */ if (!str) str = ""; if (str && str[0]) ND_has_port(aghead(e)) = TRUE; ED_head_port(e) = chkPort(ND_shape(aghead(e))->fns->portfn, aghead(e), str); if (noClip(e, E_headclip)) ED_head_port(e).clip = FALSE; return r; }
void GraphvizPlotter::parseGraphAttrs(Agraph_t *g, GraphComponent *g_component, processedProperties *props) { // prochazim vsechny mozne atributy grafu for (auto i : GraphvizAttrs::graph_attrs) { Agsym_t *attr = agattr(g, AGRAPH, (char *) i.c_str(), NULL); // pokud je dany atribut grafu k nejakemu grafu prirazen a jeste nebyl zpracovan, priradim jej ke komponente grafu if ((attr && !isWalkedObjectAttr(&props->graph_attrs, i.c_str(), attr->defval))) { std::string val(attr->defval); // pokud se nejdna o html atribut, vyescapujeme uvozovky if (!aghtmlstr(attr->defval)) { val = Utility::escape_quotes(val); } // pridani atributu g_component->setAttr(i.c_str(), val.c_str()); // pridani mezi zpracovane komponenty props->graph_attrs.insert(std::pair<std::string, std::string>(i, attr->defval)); // pokud se jedna o html atribut, nastavime priznak if (aghtmlstr(attr->defval)) { Attribute *g_attr = g_component->attrs.getAttr(i.c_str()); g_attr->setHtml(); } } } // prochazim vsechny mozne atributy vrcholu for (auto i : GraphvizAttrs::node_attrs) { Agsym_t *attr = agattr(g, AGNODE, (char *) i.c_str(), 0); // pokud je dany atribut vrcholu k nejakemu grafu prirazen a jeste nebyl zpracovan, priradim jej ke komponente grafu if (attr && !isWalkedObjectAttr(&props->node_attrs, i.c_str(), attr->defval)) { std::string val(attr->defval); // pokud se nejdna o html atribut, vyescapujeme uvozovky if (!aghtmlstr(attr->defval)) { val = Utility::escape_quotes(val); } g_component->setNodeAttr(i.c_str(), val.c_str()); props->node_attrs.insert(std::pair<std::string, std::string>(i, attr->defval)); if (aghtmlstr(attr->defval)) { Attribute *g_attr = g_component->getNodeAttrs()->getAttr(i.c_str()); g_attr->setHtml(); } } } // prochazim vsechny mozne atributy vrcholu for (auto i : GraphvizAttrs::edge_attrs) { Agsym_t *attr = agattr(g, AGEDGE, (char *) i.c_str(), 0); // pokud je dany atribut hrany k nejakemu grafu prirazen a jeste nebyl zpracovan, priradim jej ke komponente grafu if (attr && !isWalkedObjectAttr(&props->edge_attrs, i.c_str(), attr->defval)) { std::string val(attr->defval); // pokud se nejdna o html atribut, vyescapujeme uvozovky if (!aghtmlstr(attr->defval)) { val = Utility::escape_quotes(val); } g_component->setEdgeAttr(i.c_str(), val.c_str()); props->edge_attrs.insert(std::pair<std::string, std::string>(i, attr->defval)); if (aghtmlstr(attr->defval)) { Attribute *g_attr = g_component->getEdgeAttrs()->getAttr(i.c_str()); g_attr->setHtml(); } } } }